@openclaw/codex 2026.7.1-beta.6 → 2026.7.2-beta.1

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.
Files changed (46) hide show
  1. package/README.md +27 -3
  2. package/dist/app-server-policy-DVcxdse_.js +49 -0
  3. package/dist/{attempt-notifications-BGsEIIDI.js → attempt-notifications-DEv9h7iC.js} +1 -1
  4. package/dist/auth-binding-C1czuHPA.js +62 -0
  5. package/dist/capabilities-42Dfn2TV.js +33 -0
  6. package/dist/cli-metadata.js +20 -0
  7. package/dist/{app-server-policy-C968Kgin.js → command-formatters-D6ZlGNmb.js} +8 -51
  8. package/dist/{command-handlers-Dv-pzAmg.js → command-handlers-Cpl9fUWv.js} +163 -60
  9. package/dist/{compact-4mVBriKT.js → compact-FnJmiPNA.js} +40 -10
  10. package/dist/computer-use-DVzr8OP1.js +685 -0
  11. package/dist/{config-CYEDnLJ2.js → config-c48K5HP9.js} +200 -29
  12. package/dist/conversation-control-DtQ-E7mr.js +288 -0
  13. package/dist/doctor-contract-api.js +120 -81
  14. package/dist/{provider-capabilities-CDnHbmUZ.js → dynamic-tools-BMLoaTeG.js} +5246 -5140
  15. package/dist/harness.js +55 -15
  16. package/dist/index.js +1435 -265
  17. package/dist/{media-understanding-provider-BHOu9-Gg.js → media-understanding-provider-D580L0P8.js} +28 -10
  18. package/dist/media-understanding-provider.js +1 -1
  19. package/dist/{models-DDmO1zwd.js → models-DuKzZA6G.js} +1 -1
  20. package/dist/notification-correlation-DfaCm0mx.js +67 -0
  21. package/dist/plugin-app-cache-key-BKNjHMEs.js +315 -0
  22. package/dist/{protocol-2POPqAY4.js → protocol-BMifTfdW.js} +3 -1
  23. package/dist/provider-catalog.js +66 -27
  24. package/dist/provider.js +306 -1
  25. package/dist/{provider-zjPfx5Fs.js → rate-limits-Dhp04Rqo.js} +4 -261
  26. package/dist/request-DborTWgw.js +111 -0
  27. package/dist/{run-attempt-FUyOjGCV.js → run-attempt-VPVJoYDP.js} +7897 -7136
  28. package/dist/runtime-artifact-C2ITXdhM.js +488 -0
  29. package/dist/{sandbox-guard-DA2TQfZW.js → sandbox-guard-D1Wky__S.js} +10 -1
  30. package/dist/{session-binding-C1ZXdP-x.js → session-binding-BMfX1OX-.js} +247 -88
  31. package/dist/session-catalog-7H112Tr_.js +2396 -0
  32. package/dist/session-cli-B28RhCyp.js +175 -0
  33. package/dist/{shared-client-4ICy3U6d.js → shared-client-D4mFI9al.js} +1997 -1297
  34. package/dist/{side-question-N4OaDer2.js → side-question-CgJBz52s.js} +135 -67
  35. package/dist/{thread-lifecycle-qWE88Dn2.js → thread-lifecycle-BgLXzjvV.js} +747 -317
  36. package/dist/transcript-mirror-DhLwFIL4.js +485 -0
  37. package/dist/transport-stdio-DXgGZ7Ib.js +88 -0
  38. package/dist/{web-search-provider.runtime-BSlriav6.js → web-search-provider.runtime-Bs-eTn5U.js} +3 -3
  39. package/npm-shrinkwrap.json +56 -30
  40. package/openclaw.plugin.json +168 -10
  41. package/package.json +8 -6
  42. package/dist/command-rpc-eLM_mtC7.js +0 -784
  43. package/dist/computer-use-Bmaz333N.js +0 -377
  44. package/dist/notification-correlation-Bo7KB3ks.js +0 -35
  45. package/dist/plugin-app-cache-key-BrhVdeEf.js +0 -98
  46. package/dist/request-BcJyl8KL.js +0 -36
@@ -1,18 +1,20 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
- import { l as normalizeCodexServiceTier, t as CODEX_PLUGINS_MARKETPLACE_NAME } from "./config-CYEDnLJ2.js";
2
+ import { n as CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME, t as CODEX_PLUGINS_MARKETPLACE_NAME, u as normalizeCodexServiceTier } from "./config-c48K5HP9.js";
3
3
  import { n as CODEX_APP_SERVER_BINDING_NAMESPACE, t as CODEX_APP_SERVER_BINDING_MAX_ENTRIES } from "./session-binding-meta-B7aEMU7g.js";
4
4
  import { createHash, randomUUID } from "node:crypto";
5
5
  import { ensureAuthProfileStore, resolveDefaultAgentDir, resolveProviderIdForAuth, resolveSessionAgentIds } from "openclaw/plugin-sdk/agent-runtime";
6
6
  import { z } from "zod";
7
7
  import { embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
8
8
  import { AsyncLocalStorage } from "node:async_hooks";
9
- import { loadSessionStore, resolveSessionStoreEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
9
+ import { getSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
10
10
  //#region extensions/codex/src/app-server/session-binding.ts
11
11
  /** SQLite-backed Codex app-server thread bindings. */
12
12
  var session_binding_exports = /* @__PURE__ */ __exportAll({
13
13
  CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS: () => CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS,
14
14
  CODEX_APP_SERVER_BINDING_MAX_ENTRIES: () => CODEX_APP_SERVER_BINDING_MAX_ENTRIES,
15
15
  CODEX_APP_SERVER_BINDING_NAMESPACE: () => CODEX_APP_SERVER_BINDING_NAMESPACE,
16
+ CodexSupervisionBindingReplacementError: () => CodexSupervisionBindingReplacementError,
17
+ assertCodexBindingMayBeReplaced: () => assertCodexBindingMayBeReplaced,
16
18
  bindingStoreKey: () => bindingStoreKey,
17
19
  createCodexAppServerBindingStore: () => createCodexAppServerBindingStore,
18
20
  createStoredCodexAppServerBinding: () => createStoredCodexAppServerBinding,
@@ -50,6 +52,22 @@ const optionalStringSchema = z.string().optional().catch(void 0);
50
52
  const optionalBooleanSchema = z.boolean().optional().catch(void 0);
51
53
  const optionalNonBlankStringSchema = z.string().refine((value) => Boolean(value.trim())).optional().catch(void 0);
52
54
  const optionalTimestampSchema = z.string().refine((value) => Number.isFinite(Date.parse(value))).optional().catch(void 0);
55
+ const pendingSupervisionBranchSchema = z.object({
56
+ sourceThreadId: z.string().trim().min(1),
57
+ connectionFingerprint: z.string().trim().min(1).optional(),
58
+ lastTurnId: z.string().trim().min(1).optional(),
59
+ cleanupThreadIds: z.array(z.string().trim().min(1)).max(2).optional()
60
+ }).strict().superRefine((pending, context) => {
61
+ const cleanupThreadIds = pending.cleanupThreadIds ?? [];
62
+ if (new Set(cleanupThreadIds).size !== cleanupThreadIds.length) context.addIssue({
63
+ code: "custom",
64
+ message: "pending supervision cleanup thread ids must be unique"
65
+ });
66
+ if (cleanupThreadIds.includes(pending.sourceThreadId)) context.addIssue({
67
+ code: "custom",
68
+ message: "pending supervision cleanup cannot target its source"
69
+ });
70
+ });
53
71
  const contextEngineProjectionSchema = z.object({
54
72
  schemaVersion: z.literal(1),
55
73
  mode: z.literal("thread_bootstrap"),
@@ -78,7 +96,7 @@ const accountAppPolicyEntrySchema = z.object({
78
96
  const pluginAppPolicyEntrySchema = z.object({
79
97
  source: z.literal("plugin").optional(),
80
98
  configKey: z.string(),
81
- marketplaceName: z.literal(CODEX_PLUGINS_MARKETPLACE_NAME),
99
+ marketplaceName: z.enum([CODEX_PLUGINS_MARKETPLACE_NAME, CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME]),
82
100
  pluginName: z.string(),
83
101
  allowDestructiveActions: z.boolean(),
84
102
  destructiveApprovalMode: destructiveApprovalModeSchema,
@@ -91,9 +109,14 @@ const pluginAppPolicyContextSchema = z.object({
91
109
  }).strict();
92
110
  const threadBindingSchema = z.object({
93
111
  threadId: z.string().refine((value) => Boolean(value.trim())),
112
+ clientId: optionalStringSchema,
94
113
  cwd: z.string(),
114
+ connectionScope: z.literal("supervision").optional(),
115
+ supervisionSourceThreadId: z.string().trim().min(1).optional(),
95
116
  authProfileId: optionalStringSchema,
96
117
  model: optionalStringSchema,
118
+ preserveNativeModel: z.literal(true).optional().catch(void 0),
119
+ pendingSupervisionBranch: pendingSupervisionBranchSchema.optional(),
97
120
  modelProvider: z.string().transform((value) => value.trim()).pipe(z.string().min(1)).optional().catch(void 0),
98
121
  approvalPolicy: z.preprocess((value) => value === "on-failure" ? "on-request" : value, z.enum([
99
122
  "never",
@@ -113,6 +136,8 @@ const threadBindingSchema = z.object({
113
136
  webSearchThreadConfigFingerprint: optionalStringSchema,
114
137
  userMcpServersFingerprint: optionalStringSchema,
115
138
  mcpServersFingerprint: optionalStringSchema,
139
+ ringZeroConfigFingerprint: optionalStringSchema,
140
+ ringZeroClientInstanceId: optionalStringSchema,
116
141
  nativeHookRelayGeneration: optionalNonBlankStringSchema,
117
142
  appServerRuntimeFingerprint: optionalStringSchema,
118
143
  pluginAppsFingerprint: optionalStringSchema,
@@ -123,7 +148,56 @@ const threadBindingSchema = z.object({
123
148
  conversationStartId: optionalStringSchema,
124
149
  conversationSourceTransferComplete: z.literal(true).optional().catch(void 0),
125
150
  historyCoveredThrough: optionalTimestampSchema
151
+ }).superRefine((binding, context) => {
152
+ if (binding.connectionScope === "supervision") {
153
+ if (!binding.supervisionSourceThreadId) context.addIssue({
154
+ code: "custom",
155
+ message: "supervision connection ownership requires its native source thread id"
156
+ });
157
+ if (binding.preserveNativeModel !== true) context.addIssue({
158
+ code: "custom",
159
+ message: "supervision connection ownership requires native model ownership"
160
+ });
161
+ if (binding.conversationSourceTransferComplete !== true) context.addIssue({
162
+ code: "custom",
163
+ message: "supervision connection ownership requires a completed source transfer"
164
+ });
165
+ if (!binding.pendingSupervisionBranch && (!binding.model?.trim() || !binding.modelProvider)) context.addIssue({
166
+ code: "custom",
167
+ message: "materialized supervision bindings require a native model and provider"
168
+ });
169
+ }
170
+ if (binding.supervisionSourceThreadId && binding.connectionScope !== "supervision") context.addIssue({
171
+ code: "custom",
172
+ message: "a supervision source thread id requires supervision connection ownership"
173
+ });
174
+ if (!binding.pendingSupervisionBranch) return;
175
+ if (binding.threadId !== binding.pendingSupervisionBranch.sourceThreadId) context.addIssue({
176
+ code: "custom",
177
+ message: "pending supervision source must match the provisional thread binding"
178
+ });
179
+ if (binding.supervisionSourceThreadId !== binding.pendingSupervisionBranch.sourceThreadId) context.addIssue({
180
+ code: "custom",
181
+ message: "pending supervision source must match its durable source identity"
182
+ });
183
+ if (binding.preserveNativeModel !== true) context.addIssue({
184
+ code: "custom",
185
+ message: "pending supervision bindings must defer model selection to Codex App Server"
186
+ });
187
+ if (binding.connectionScope !== "supervision") context.addIssue({
188
+ code: "custom",
189
+ message: "pending supervision bindings require supervision connection ownership"
190
+ });
126
191
  });
192
+ var CodexSupervisionBindingReplacementError = class extends Error {
193
+ constructor(threadId, operation) {
194
+ super(`Refusing to replace supervised Codex thread ${threadId} while ${operation}; its native user-home connection and model ownership must be preserved`);
195
+ this.name = "CodexSupervisionBindingReplacementError";
196
+ }
197
+ };
198
+ function assertCodexBindingMayBeReplaced(binding, operation) {
199
+ if (binding?.connectionScope === "supervision") throw new CodexSupervisionBindingReplacementError(binding.threadId, operation);
200
+ }
127
201
  const bindingLeaseSchema = z.object({
128
202
  token: z.string().refine((value) => Boolean(value.trim())),
129
203
  expiresAt: z.number().finite()
@@ -205,13 +279,14 @@ async function reclaimCurrentCodexSessionGeneration(params) {
205
279
  const plan = await params.bindingStore.prepareSessionGenerationReclaim(params.identity);
206
280
  if (plan.kind === "resolved") return plan.result;
207
281
  try {
208
- if (resolveSessionStoreEntry({
209
- store: loadSessionStore(resolveStorePath(params.config?.session?.store, { agentId: params.identity.agentId }), {
210
- skipCache: true,
211
- hydrateSkillPromptRefs: false
212
- }),
213
- sessionKey
214
- }).existing?.sessionId !== params.identity.sessionId) return false;
282
+ const storePath = resolveStorePath(params.config?.session?.store, { agentId: params.identity.agentId });
283
+ if (getSessionEntry({
284
+ agentId: params.identity.agentId,
285
+ hydrateSkillPromptRefs: false,
286
+ readConsistency: "latest",
287
+ sessionKey,
288
+ storePath
289
+ })?.sessionId !== params.identity.sessionId) return false;
215
290
  } catch {
216
291
  return false;
217
292
  }
@@ -225,6 +300,32 @@ function createCodexAppServerBindingStore(state) {
225
300
  const update = state.update?.bind(state);
226
301
  if (!update) throw new Error("Codex app-server bindings require atomic plugin-state updates");
227
302
  const leaseContext = new AsyncLocalStorage();
303
+ const archiveContext = new AsyncLocalStorage();
304
+ let activeBindingMutations = 0;
305
+ let pendingArchives = 0;
306
+ let archiveTail = Promise.resolve();
307
+ let bindingMutationsDrained = [];
308
+ const waitForBindingMutations = async () => {
309
+ if (activeBindingMutations === 0) return;
310
+ await new Promise((resolve) => {
311
+ bindingMutationsDrained.push(resolve);
312
+ });
313
+ };
314
+ const runBindingMutation = async (run) => {
315
+ if (archiveContext.getStore() === true) return await run();
316
+ if (pendingArchives > 0) throw new Error("Codex binding mutation blocked while a native archive is in progress; retry");
317
+ activeBindingMutations += 1;
318
+ try {
319
+ return await run();
320
+ } finally {
321
+ activeBindingMutations -= 1;
322
+ if (activeBindingMutations === 0) {
323
+ const drained = bindingMutationsDrained;
324
+ bindingMutationsDrained = [];
325
+ for (const resolve of drained) resolve();
326
+ }
327
+ }
328
+ };
228
329
  const renewLease = (key, owner) => {
229
330
  if (owner.failure) return;
230
331
  try {
@@ -293,6 +394,16 @@ function createCodexAppServerBindingStore(state) {
293
394
  if (raw !== void 0 && !stored) throw new Error(`Invalid Codex app-server binding row: ${key}`);
294
395
  return stored?.state === "active" && ownsStoredSessionGeneration(identity, stored) ? stored.binding : void 0;
295
396
  },
397
+ async hasOtherThreadOwner(threadId, currentIdentity) {
398
+ const currentKey = currentIdentity ? bindingStoreKey(currentIdentity) : void 0;
399
+ return state.entries().some(({ key, value }) => {
400
+ const stored = readStoredCodexAppServerBinding(value);
401
+ if (!stored) throw new Error(`Invalid Codex app-server binding row: ${key}`);
402
+ const isCurrentOwner = currentIdentity !== void 0 && key === currentKey && (currentIdentity.kind === "conversation" || stored.sessionId === currentIdentity.sessionId.trim());
403
+ if (stored.state !== "active" || stored.binding.threadId !== threadId || isCurrentOwner) return false;
404
+ return true;
405
+ });
406
+ },
296
407
  async prepareSessionGenerationReclaim(identity) {
297
408
  const key = bindingStoreKey(identity);
298
409
  const raw = state.lookup(key);
@@ -313,94 +424,126 @@ function createCodexAppServerBindingStore(state) {
313
424
  };
314
425
  },
315
426
  async mutate(identity, mutation) {
316
- const key = bindingStoreKey(identity);
317
- const retainLegacyClear = mutation.kind === "clear" && key.startsWith("conversation:legacy-");
318
- return await transactKey(key, (current, leaseToken) => {
319
- const ownsGeneration = ownsStoredSessionGeneration(identity, current);
320
- const ownedLease = current?.lease && current.lease.token === leaseToken ? { lease: current.lease } : {};
321
- if (mutation.kind === "reclaim-generation") {
322
- if (identity.kind !== "session" || !identity.sessionKey?.trim()) return { result: false };
323
- if (!current) return { result: true };
324
- if (ownsGeneration) return { result: current.state !== "cleared" || current.retired !== true };
325
- if (current.sessionId !== mutation.expectedPreviousSessionId) return { result: false };
326
- return {
427
+ return await runBindingMutation(async () => {
428
+ const key = bindingStoreKey(identity);
429
+ const retainLegacyClear = mutation.kind === "clear" && key.startsWith("conversation:legacy-");
430
+ return await transactKey(key, (current, leaseToken) => {
431
+ const ownsGeneration = ownsStoredSessionGeneration(identity, current);
432
+ const ownedLease = current?.lease && current.lease.token === leaseToken ? { lease: current.lease } : {};
433
+ if (mutation.kind === "reclaim-generation") {
434
+ if (identity.kind !== "session" || !identity.sessionKey?.trim()) return { result: false };
435
+ if (!current) return { result: true };
436
+ if (ownsGeneration) return { result: current.state !== "cleared" || current.retired !== true };
437
+ if (current.sessionId !== mutation.expectedPreviousSessionId) return { result: false };
438
+ if (current.state === "active" && current.binding.connectionScope === "supervision") return { result: false };
439
+ return {
440
+ result: true,
441
+ next: {
442
+ version: 1,
443
+ state: "cleared",
444
+ sessionId: identity.sessionId,
445
+ ...ownedLease
446
+ }
447
+ };
448
+ }
449
+ const storedActive = current?.state === "active" ? current : void 0;
450
+ const active = ownsGeneration ? storedActive : void 0;
451
+ const retiredGeneration = current?.state === "cleared" && current.retired === true && ownsGeneration;
452
+ const preservesSupervisionOwner = mutation.kind === "set" && active?.binding.connectionScope === "supervision" && isSameSupervisionOwner(active.binding, mutation.binding);
453
+ const clearsPendingSupervisionOwner = mutation.kind === "clear" && active?.binding.connectionScope === "supervision" && matchesPendingSupervisionClear(active.binding, mutation.threadId, mutation.expectedPendingSupervisionBranch);
454
+ if (mutation.kind === "set" && (mutation.if?.kind === "absent" && storedActive || current !== void 0 && !ownsGeneration || retiredGeneration || active?.binding.connectionScope === "supervision" && !preservesSupervisionOwner) || mutation.kind === "patch" && active?.binding.threadId !== mutation.threadId || (mutation.kind === "patch-pending-supervision-branch" || mutation.kind === "commit-pending-supervision-branch") && !matchesPendingSupervisionBranch(active?.binding, mutation.expected) || mutation.kind === "clear" && (mutation.threadId !== void 0 && active?.binding.threadId !== mutation.threadId || !ownsGeneration || active?.binding.connectionScope === "supervision" && !clearsPendingSupervisionOwner)) return { result: false };
455
+ if (mutation.kind === "clear" && retiredGeneration) return { result: true };
456
+ if (mutation.kind === "clear") return {
327
457
  result: true,
328
458
  next: {
329
459
  version: 1,
330
460
  state: "cleared",
331
- sessionId: identity.sessionId,
461
+ ...storedSessionGeneration(identity, current),
332
462
  ...ownedLease
333
463
  }
334
464
  };
335
- }
336
- const storedActive = current?.state === "active" ? current : void 0;
337
- const active = ownsGeneration ? storedActive : void 0;
338
- const retiredGeneration = current?.state === "cleared" && current.retired === true && ownsGeneration;
339
- if (mutation.kind === "set" && (mutation.if?.kind === "absent" && storedActive || current !== void 0 && !ownsGeneration || retiredGeneration) || mutation.kind === "patch" && active?.binding.threadId !== mutation.threadId || mutation.kind === "clear" && (mutation.threadId !== void 0 && active?.binding.threadId !== mutation.threadId || !ownsGeneration)) return { result: false };
340
- if (mutation.kind === "clear" && retiredGeneration) return { result: true };
341
- if (mutation.kind === "clear") return {
342
- result: true,
343
- next: {
344
- version: 1,
345
- state: "cleared",
346
- ...storedSessionGeneration(identity, current),
347
- ...ownedLease
348
- }
349
- };
350
- let binding;
351
- if (mutation.kind === "set") binding = validateBindingForWrite(mutation.binding);
352
- else binding = validateBindingForWrite({
353
- ...active.binding,
354
- ...mutation.patch,
355
- threadId: mutation.threadId
356
- });
357
- return {
358
- result: true,
359
- next: {
360
- version: 1,
361
- state: "active",
362
- binding,
363
- ...storedSessionGeneration(identity, current),
364
- ...ownedLease
365
- }
366
- };
367
- }, mutation.kind === "clear" && !retainLegacyClear && !leaseContext.getStore()?.has(key) ? 1 : void 0);
465
+ let binding;
466
+ if (mutation.kind === "set") binding = validateBindingForWrite(mutation.binding);
467
+ else if (mutation.kind === "patch-pending-supervision-branch") binding = validateBindingForWrite({
468
+ ...active.binding,
469
+ pendingSupervisionBranch: mutation.pending
470
+ });
471
+ else if (mutation.kind === "commit-pending-supervision-branch") binding = validateBindingForWrite({
472
+ ...active.binding,
473
+ ...mutation.patch,
474
+ threadId: mutation.threadId,
475
+ pendingSupervisionBranch: void 0
476
+ });
477
+ else binding = validateBindingForWrite({
478
+ ...active.binding,
479
+ ...mutation.patch,
480
+ threadId: mutation.threadId
481
+ });
482
+ return {
483
+ result: true,
484
+ next: {
485
+ version: 1,
486
+ state: "active",
487
+ binding,
488
+ ...storedSessionGeneration(identity, current),
489
+ ...ownedLease
490
+ }
491
+ };
492
+ }, mutation.kind === "clear" && !retainLegacyClear && !leaseContext.getStore()?.has(key) ? 1 : void 0);
493
+ });
368
494
  },
369
495
  async adoptSessionGeneration(identity, expectedPreviousSessionId) {
370
- const key = bindingStoreKey(identity);
371
- const expectedSessionId = expectedPreviousSessionId.trim();
372
- const targetSessionId = identity.sessionId.trim();
373
- if (!expectedSessionId) throw new Error("Codex session generation adoption requires the previous session id");
374
- return await transactKey(key, (current) => {
375
- if (current?.state !== "active") return { result: "absent" };
376
- if (current.sessionId === targetSessionId) return { result: "current" };
377
- if (current.sessionId !== expectedSessionId) return { result: "conflict" };
378
- return {
379
- result: "adopted",
380
- next: {
381
- ...current,
382
- sessionId: targetSessionId
383
- }
384
- };
496
+ return await runBindingMutation(async () => {
497
+ const key = bindingStoreKey(identity);
498
+ const expectedSessionId = expectedPreviousSessionId.trim();
499
+ const targetSessionId = identity.sessionId.trim();
500
+ if (!expectedSessionId) throw new Error("Codex session generation adoption requires the previous session id");
501
+ return await transactKey(key, (current) => {
502
+ if (current?.state !== "active") return { result: "absent" };
503
+ if (current.sessionId === targetSessionId) return { result: "current" };
504
+ if (current.sessionId !== expectedSessionId) return { result: "conflict" };
505
+ return {
506
+ result: "adopted",
507
+ next: {
508
+ ...current,
509
+ sessionId: targetSessionId
510
+ }
511
+ };
512
+ });
385
513
  });
386
514
  },
387
515
  async retireSessionGeneration(identity) {
388
- const key = bindingStoreKey(identity);
389
- return await transactKey(key, (current, leaseToken) => {
390
- if (!current) return { result: "absent" };
391
- if (!ownsStoredSessionGeneration(identity, current)) return { result: "conflict" };
392
- if (current.state === "cleared" && current.retired === true) return { result: "applied" };
393
- return {
394
- result: "applied",
395
- next: {
396
- version: 1,
397
- state: "cleared",
398
- retired: true,
399
- ...storedSessionGeneration(identity, current),
400
- ...current.lease && current.lease.token === leaseToken ? { lease: current.lease } : {}
401
- }
402
- };
403
- }, identity.sessionKey?.trim() ? void 0 : PHYSICAL_SESSION_RETIRE_TTL_MS);
516
+ return await runBindingMutation(async () => {
517
+ const key = bindingStoreKey(identity);
518
+ return await transactKey(key, (current, leaseToken) => {
519
+ if (!current) return { result: "absent" };
520
+ if (!ownsStoredSessionGeneration(identity, current)) return { result: "conflict" };
521
+ if (current.state === "cleared" && current.retired === true) return { result: "applied" };
522
+ return {
523
+ result: "applied",
524
+ next: {
525
+ version: 1,
526
+ state: "cleared",
527
+ retired: true,
528
+ ...storedSessionGeneration(identity, current),
529
+ ...current.lease && current.lease.token === leaseToken ? { lease: current.lease } : {}
530
+ }
531
+ };
532
+ }, identity.sessionKey?.trim() ? void 0 : PHYSICAL_SESSION_RETIRE_TTL_MS);
533
+ });
534
+ },
535
+ async withThreadArchiveFence(run) {
536
+ pendingArchives += 1;
537
+ const operation = archiveTail.then(async () => {
538
+ await waitForBindingMutations();
539
+ return await archiveContext.run(true, run);
540
+ });
541
+ archiveTail = operation.then(() => void 0, () => void 0);
542
+ try {
543
+ return await operation;
544
+ } finally {
545
+ pendingArchives -= 1;
546
+ }
404
547
  },
405
548
  async withLease(identity, run) {
406
549
  const key = bindingStoreKey(identity);
@@ -477,6 +620,22 @@ function createCodexAppServerBindingStore(state) {
477
620
  }
478
621
  };
479
622
  }
623
+ function matchesPendingSupervisionBranch(binding, expected) {
624
+ const pending = binding?.pendingSupervisionBranch;
625
+ if (!pending || binding?.threadId !== expected.sourceThreadId) return false;
626
+ if (pending.sourceThreadId !== expected.sourceThreadId || pending.connectionFingerprint !== expected.connectionFingerprint || pending.lastTurnId !== expected.lastTurnId) return false;
627
+ const currentCleanup = pending.cleanupThreadIds ?? [];
628
+ const expectedCleanup = expected.cleanupThreadIds ?? [];
629
+ return currentCleanup.length === expectedCleanup.length && currentCleanup.every((threadId, index) => threadId === expectedCleanup[index]);
630
+ }
631
+ function isSameSupervisionOwner(current, replacement) {
632
+ return replacement.connectionScope === "supervision" && replacement.threadId === current.threadId && replacement.supervisionSourceThreadId === current.supervisionSourceThreadId;
633
+ }
634
+ function matchesPendingSupervisionClear(binding, threadId, expected) {
635
+ if (!expected) return false;
636
+ const sourceThreadId = expected.sourceThreadId;
637
+ return threadId === sourceThreadId && binding.supervisionSourceThreadId === sourceThreadId && matchesPendingSupervisionBranch(binding, expected);
638
+ }
480
639
  /** Stable plugin-state key for one current binding owner. */
481
640
  function bindingStoreKey(identity) {
482
641
  if (identity.kind === "session") {
@@ -555,7 +714,7 @@ function readPluginAppPolicyContext(value, bindingSchemaVersion) {
555
714
  };
556
715
  continue;
557
716
  }
558
- if ("appId" in entry || entry.source !== void 0 && entry.source !== "plugin" || typeof entry.configKey !== "string" || entry.marketplaceName !== "openai-curated" || typeof entry.pluginName !== "string" || typeof entry.allowDestructiveActions !== "boolean" || destructiveApprovalMode === "invalid" || !mcpServerNamesValid) return;
717
+ if ("appId" in entry || entry.source !== void 0 && entry.source !== "plugin" || typeof entry.configKey !== "string" || entry.marketplaceName !== "openai-curated" && entry.marketplaceName !== "workspace-directory" || typeof entry.pluginName !== "string" || typeof entry.allowDestructiveActions !== "boolean" || destructiveApprovalMode === "invalid" || !mcpServerNamesValid) return;
559
718
  parsedApps[appId] = {
560
719
  configKey: entry.configKey,
561
720
  marketplaceName: entry.marketplaceName,
@@ -624,4 +783,4 @@ function resolveCodexAppServerBindingModelProvider(params) {
624
783
  return params.modelProvider?.trim() || (isCodexAppServerNativeAuthProfile(params) ? PUBLIC_OPENAI_MODEL_PROVIDER : void 0);
625
784
  }
626
785
  //#endregion
627
- export { normalizeCodexAppServerBindingModelProvider as a, session_binding_exports as c, isCodexAppServerNativeAuthProfile as i, bindingStoreKey as n, reclaimCurrentCodexSessionGeneration as o, hashCodexAppServerBindingFingerprint as r, sessionBindingIdentity as s, CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS as t };
786
+ export { isCodexAppServerNativeAuthProfile as a, sessionBindingIdentity as c, hashCodexAppServerBindingFingerprint as i, session_binding_exports as l, assertCodexBindingMayBeReplaced as n, normalizeCodexAppServerBindingModelProvider as o, bindingStoreKey as r, reclaimCurrentCodexSessionGeneration as s, CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS as t };