codex-overleaf-link 2.3.0 → 2.3.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.
Files changed (50) hide show
  1. package/README.md +23 -23
  2. package/extension/bootstrap/manifest.template.json +1 -1
  3. package/extension/src/background.js +20 -0
  4. package/extension/src/content/assetTransferBroker.js +169 -0
  5. package/extension/src/content/composerPanel.js +0 -2
  6. package/extension/src/content/contentRuntime.js +135 -111
  7. package/extension/src/content/generated/content.bundle.js +1066 -345
  8. package/extension/src/content/generated/content.bundle.meta.json +7 -3
  9. package/extension/src/content/legacyGlobalRegistry.js +3 -0
  10. package/extension/src/content/markdownText.js +12 -10
  11. package/extension/src/content/mathText.js +155 -9
  12. package/extension/src/content/modelPicker.js +2 -2
  13. package/extension/src/content/modelPickerSupport.js +3 -3
  14. package/extension/src/content/nativeCompatibilityController.js +2 -2
  15. package/extension/src/content/otWarmMirror.js +1 -1
  16. package/extension/src/content/pageBridgeClient.js +1 -0
  17. package/extension/src/content/runResultActions.js +114 -0
  18. package/extension/src/content/runTimelineView.js +23 -0
  19. package/extension/src/content/sessionForkController.js +120 -0
  20. package/extension/src/content/writebackController.js +3 -0
  21. package/extension/src/content/writebackOrchestrator.js +5 -50
  22. package/extension/src/page/binaryAssetUploader.js +343 -0
  23. package/extension/src/page/trackedChangesLifecycle.js +12 -4
  24. package/extension/src/page/writebackRouter.js +6 -2
  25. package/extension/src/pageBridge.js +30 -1
  26. package/extension/src/shared/agentTranscript.js +10 -3
  27. package/extension/src/shared/compatibility.js +4 -2
  28. package/extension/src/shared/i18n.js +18 -4
  29. package/extension/src/shared/models.js +13 -2
  30. package/extension/src/shared/pageRpcContract.js +6 -2
  31. package/extension/src/shared/runExecutionSnapshot.js +14 -4
  32. package/extension/src/shared/runExecutionSnapshotCodec.js +5 -2
  33. package/extension/src/shared/scopedPersistenceQueuePolicy.js +20 -1
  34. package/extension/src/shared/scopedPersistenceReceipt.js +60 -0
  35. package/extension/src/shared/scopedPersistenceTransaction.js +50 -47
  36. package/extension/src/shared/sessionState.js +58 -15
  37. package/extension/src/shared/storageDb.js +6 -5
  38. package/extension/src/shared/storageRunActions.js +11 -1
  39. package/extension/src/shared/writebackOperationEvidence.js +16 -6
  40. package/extension/src/shared/writebackSettlement.js +28 -6
  41. package/extension/styles/panel.css +79 -8
  42. package/native-host/src/codexModels.js +6 -2
  43. package/native-host/src/codexPromptAssembly.js +1 -1
  44. package/native-host/src/codexSessionRunner.js +5 -1
  45. package/native-host/src/codexThreadFork.js +103 -0
  46. package/native-host/src/mirrorWorkspace.js +5 -19
  47. package/native-host/src/nativeAssetTransfer.js +183 -0
  48. package/native-host/src/taskRunnerRuntime.js +33 -81
  49. package/native-host/src/updateManager.js +36 -1
  50. package/package.json +1 -1
@@ -1697,10 +1697,17 @@
1697
1697
  if (providerError) {
1698
1698
  return providerError;
1699
1699
  }
1700
- if (/Mode must be "confirm" or "auto"/i.test(text)) {
1700
+ if (/suggest_mode_removed|Suggest mode has been removed/i.test(text)) {
1701
+ return {
1702
+ conclusion: textFor(locale, "\u5EFA\u8BAE\u4FEE\u6539\u6A21\u5F0F\u5DF2\u7ECF\u79FB\u9664\u3002", "Suggest mode has been removed."),
1703
+ nextStep: textFor(locale, "\u8BF7\u5237\u65B0\u6269\u5C55\uFF0C\u7136\u540E\u9009\u62E9\u201C\u53EA\u95EE\u4E0D\u6539\u201D\u6216\u201C\u81EA\u52A8\u5199\u5165\u201D\u3002", "Reload the extension, then choose Ask or Auto."),
1704
+ failureCode: "suggest_mode_removed"
1705
+ };
1706
+ }
1707
+ if (/Mode must be "(?:confirm|ask)" or "auto"/i.test(text)) {
1701
1708
  return {
1702
1709
  conclusion: textFor(locale, "\u8FD9\u8F6E\u6CA1\u6709\u5199\u5165\uFF1A\u5F53\u524D\u662F\u201C\u53EA\u95EE\u4E0D\u6539\u201D\uFF0C\u4F46\u8FD9\u4E2A\u4EFB\u52A1\u9700\u8981\u5199\u5165\u6743\u9650\u3002", "No files were written: this task needs write access, but the current mode is Ask."),
1703
- nextStep: textFor(locale, "\u8BF7\u5207\u6362\u5230\u201C\u5EFA\u8BAE\u4FEE\u6539\u201D\u6216\u201C\u81EA\u52A8\u5199\u5165\u201D\u540E\u91CD\u65B0\u8FD0\u884C\u3002", "Switch to Suggest or Auto and run the task again."),
1710
+ nextStep: textFor(locale, "\u8BF7\u5207\u6362\u5230\u201C\u81EA\u52A8\u5199\u5165\u201D\u540E\u91CD\u65B0\u8FD0\u884C\u3002", "Switch to Auto and run the task again."),
1704
1711
  failureCode: null
1705
1712
  // no direct catalog match — preflight / governance
1706
1713
  };
@@ -1772,7 +1779,7 @@
1772
1779
  if (/checkpoint/i.test(text)) {
1773
1780
  return {
1774
1781
  conclusion: textFor(locale, "\u8FD9\u8F6E\u6CA1\u6709\u81EA\u52A8\u5199\u5165\uFF1ACodex \u6CA1\u6709\u62FF\u5230\u53EF\u6062\u590D\u7248\u672C\u3002", "This run did not auto-write: Codex did not get a recoverable version."),
1775
- nextStep: textFor(locale, "\u8BF7\u5207\u6362\u5230\u201C\u5EFA\u8BAE\u4FEE\u6539\u201D\uFF0C\u6216\u786E\u8BA4 Overleaf Reviewing \u5DF2\u5F00\u542F\u540E\u518D\u7528\u201C\u81EA\u52A8\u5199\u5165\u201D\u3002", "Switch to Suggest, or confirm Overleaf Reviewing is enabled before using Auto."),
1782
+ nextStep: textFor(locale, "\u8BF7\u786E\u8BA4 Overleaf Reviewing \u5DF2\u5F00\u542F\u540E\u518D\u7528\u201C\u81EA\u52A8\u5199\u5165\u201D\u3002", "Confirm that Overleaf Reviewing is enabled before using Auto."),
1776
1783
  failureCode: null
1777
1784
  // no current catalog code; preflight reviewing issue
1778
1785
  };
@@ -4161,6 +4168,14 @@ ${block}`;
4161
4168
  deleteSessionHistoryFailedToast: "Deleted this plugin session, but the matching plugin-local Codex thread history was not fully cleared: {message}",
4162
4169
  deleteSessionNoThreadToast: "Deleted this plugin session. This old session had no identifiable local Codex thread history, so no local history was cleared.",
4163
4170
  deleteSessionDoneToast: "Deleted this plugin session.",
4171
+ forkRunTitle: "Fork a new conversation from this turn",
4172
+ forkRunUnavailable: "This turn cannot be forked because its Codex thread position is unavailable.",
4173
+ forkRunFailed: "Could not fork this conversation.",
4174
+ forkRunDone: "Forked conversation created.",
4175
+ forkSessionTitle: "{title} (fork)",
4176
+ copyConclusionTitle: "Copy conclusion",
4177
+ copyConclusionDone: "Conclusion copied",
4178
+ copyConclusionFailed: "Could not copy conclusion",
4164
4179
  modeSwitchFailedToast: "Could not switch mode: {message}",
4165
4180
  diffAccepted: "Accepted",
4166
4181
  diffRejected: "Rejected",
@@ -4333,8 +4348,6 @@ ${block}`;
4333
4348
  writeMode: "Write mode",
4334
4349
  modeAsk: "Ask",
4335
4350
  modeAskTitle: "Read and analyze only. Do not write to Overleaf.",
4336
- modeConfirm: "Suggest",
4337
- modeConfirmTitle: "Show a change plan first, then write after approval.",
4338
4351
  modeAuto: "Auto",
4339
4352
  modeAutoTitle: "Write directly after authorization. Deletes still require confirmation.",
4340
4353
  addContext: "Add @ context",
@@ -4470,6 +4483,7 @@ ${block}`;
4470
4483
  refreshProbeDone: "Refreshed: {status}",
4471
4484
  refreshProbeFailed: "Refresh failed. Reload Overleaf and try again.",
4472
4485
  processedFailed: "Failed {elapsed}",
4486
+ processedCancelled: "Cancelled {elapsed}",
4473
4487
  processing: "Running {elapsed}",
4474
4488
  processed: "Done {elapsed}",
4475
4489
  restoredRunStoppedTitle: "Stopped tracking this run after a page refresh",
@@ -4674,6 +4688,14 @@ ${block}`;
4674
4688
  deleteSessionHistoryFailedToast: "\u5DF2\u5220\u9664\u8FD9\u4E2A\u63D2\u4EF6\u4F1A\u8BDD\uFF0C\u4F46\u5BF9\u5E94\u7684\u63D2\u4EF6\u672C\u5730 Codex \u7EBF\u7A0B\u5386\u53F2\u6CA1\u6709\u6E05\u7406\u5B8C\u6210\uFF1A{message}",
4675
4689
  deleteSessionNoThreadToast: "\u5DF2\u5220\u9664\u8FD9\u4E2A\u63D2\u4EF6\u4F1A\u8BDD\uFF1B\u8FD9\u4E2A\u65E7\u4F1A\u8BDD\u6CA1\u6709\u53EF\u8BC6\u522B\u7684\u672C\u5730 Codex \u7EBF\u7A0B\u5386\u53F2\uFF0C\u672A\u6E05\u7406\u672C\u5730\u5386\u53F2\u3002",
4676
4690
  deleteSessionDoneToast: "\u5DF2\u5220\u9664\u8FD9\u4E2A\u63D2\u4EF6\u4F1A\u8BDD\u3002",
4691
+ forkRunTitle: "\u4ECE\u6B64\u8F6E\u5206\u53C9\u4E00\u4E2A\u65B0\u5BF9\u8BDD",
4692
+ forkRunUnavailable: "\u8BE5\u8F6E\u7F3A\u5C11\u53EF\u5B9A\u4F4D\u7684 Codex thread \u8282\u70B9\uFF0C\u65E0\u6CD5\u5206\u53C9\u3002",
4693
+ forkRunFailed: "\u65E0\u6CD5\u5206\u53C9\u6B64\u5BF9\u8BDD\u3002",
4694
+ forkRunDone: "\u5DF2\u521B\u5EFA\u5206\u53C9\u5BF9\u8BDD\u3002",
4695
+ forkSessionTitle: "{title}\uFF08\u5206\u53C9\uFF09",
4696
+ copyConclusionTitle: "\u590D\u5236\u7ED3\u8BBA",
4697
+ copyConclusionDone: "\u5DF2\u590D\u5236\u7ED3\u8BBA",
4698
+ copyConclusionFailed: "\u65E0\u6CD5\u590D\u5236\u7ED3\u8BBA",
4677
4699
  modeSwitchFailedToast: "\u5207\u6362\u6A21\u5F0F\u5931\u8D25\uFF1A{message}",
4678
4700
  diffAccepted: "\u5DF2\u63A5\u53D7",
4679
4701
  diffRejected: "\u5DF2\u62D2\u7EDD",
@@ -4846,8 +4868,6 @@ ${block}`;
4846
4868
  writeMode: "\u5199\u5165\u6A21\u5F0F",
4847
4869
  modeAsk: "\u53EA\u95EE\u4E0D\u6539",
4848
4870
  modeAskTitle: "\u53EA\u8BFB\u53D6\u548C\u5206\u6790\uFF0C\u4E0D\u5199\u5165 Overleaf",
4849
- modeConfirm: "\u5EFA\u8BAE\u4FEE\u6539",
4850
- modeConfirmTitle: "\u5148\u7ED9\u51FA\u4FEE\u6539\u65B9\u6848\uFF0C\u786E\u8BA4\u540E\u5199\u5165",
4851
4871
  modeAuto: "\u81EA\u52A8\u5199\u5165",
4852
4872
  modeAutoTitle: "\u6388\u6743\u540E\u76F4\u63A5\u5199\u5165\uFF0C\u5220\u9664\u4ECD\u9700\u786E\u8BA4",
4853
4873
  addContext: "\u6DFB\u52A0 @ \u4E0A\u4E0B\u6587",
@@ -4983,6 +5003,7 @@ ${block}`;
4983
5003
  refreshProbeDone: "\u5DF2\u91CD\u65B0\u68C0\u6D4B\uFF1A{status}",
4984
5004
  refreshProbeFailed: "\u68C0\u6D4B\u5931\u8D25\uFF1A\u8BF7\u5237\u65B0 Overleaf \u9875\u9762\u540E\u91CD\u8BD5",
4985
5005
  processedFailed: "\u5904\u7406\u5931\u8D25 {elapsed}",
5006
+ processedCancelled: "\u5DF2\u53D6\u6D88 {elapsed}",
4986
5007
  processing: "\u5904\u7406\u4E2D {elapsed}",
4987
5008
  processed: "\u5DF2\u5904\u7406 {elapsed}",
4988
5009
  restoredRunStoppedTitle: "\u9875\u9762\u5237\u65B0\u540E\u5DF2\u505C\u6B62\u8DDF\u8E2A\u8FD9\u8F6E\u4EFB\u52A1",
@@ -5188,18 +5209,27 @@ ${block}`;
5188
5209
  const normalized = {
5189
5210
  id,
5190
5211
  label,
5191
- reasoningEfforts: Array.isArray(model?.reasoningEfforts) ? model.reasoningEfforts.slice() : [],
5212
+ reasoningEfforts: normalizeReasoningEfforts(model?.reasoningEfforts),
5192
5213
  reasoningPresentation: typeof model?.reasoningPresentation === "string" ? model.reasoningPresentation : "",
5193
5214
  speedTiers: normalizeSpeedTiers(model?.speedTiers)
5194
5215
  };
5195
5216
  if (Object.prototype.hasOwnProperty.call(Object(model), "defaultReasoningEffort")) {
5196
- normalized.defaultReasoningEffort = model.defaultReasoningEffort;
5217
+ normalized.defaultReasoningEffort = normalizeReasoningEffort(model.defaultReasoningEffort);
5197
5218
  }
5198
5219
  if (Object.prototype.hasOwnProperty.call(Object(model), "defaultSpeedTier")) {
5199
5220
  normalized.defaultSpeedTier = model.defaultSpeedTier;
5200
5221
  }
5201
5222
  return normalized;
5202
5223
  }
5224
+ function normalizeReasoningEfforts(reasoningEfforts) {
5225
+ if (!Array.isArray(reasoningEfforts)) {
5226
+ return [];
5227
+ }
5228
+ return Array.from(new Set(reasoningEfforts.map(normalizeReasoningEffort).filter(Boolean)));
5229
+ }
5230
+ function normalizeReasoningEffort(reasoningEffort) {
5231
+ return normalizeModelId(reasoningEffort);
5232
+ }
5203
5233
  function normalizeSpeedTiers(speedTiers) {
5204
5234
  if (!Array.isArray(speedTiers)) {
5205
5235
  return ["standard"];
@@ -5498,7 +5528,7 @@ ${block}`;
5498
5528
  })(typeof window !== "undefined" ? window : globalThis, function runExecutionSnapshotCodecFactory() {
5499
5529
  "use strict";
5500
5530
  const SCHEMA_VERSION = 1;
5501
- const VALID_MODES = /* @__PURE__ */ new Set(["ask", "confirm", "auto"]);
5531
+ const VALID_MODES = /* @__PURE__ */ new Set(["ask", "auto"]);
5502
5532
  const VALID_SOURCES = /* @__PURE__ */ new Set(["submitted", "legacy-captured", "legacy-inferred"]);
5503
5533
  const TUPLE_FIELDS = Object.freeze([
5504
5534
  "mode",
@@ -5515,12 +5545,15 @@ ${block}`;
5515
5545
  function normalizeSnapshot(value = {}, options2 = {}) {
5516
5546
  const input = value && typeof value === "object" ? value : {};
5517
5547
  assertNoSecretFields(input);
5548
+ if (input.mode === "confirm" && options2.migrateLegacyConfirm !== true) {
5549
+ throw snapshotError("suggest_mode_removed", "Suggest mode has been removed. Choose Ask or Auto.");
5550
+ }
5518
5551
  const providerId = normalizeText(input.providerId) || "builtin";
5519
5552
  const revision = normalizeRevisionResult(input.providerRevision);
5520
5553
  if (!revision.ok) throw snapshotError("provider_revision_conflict", revision.error);
5521
5554
  const snapshot = {
5522
5555
  schemaVersion: SCHEMA_VERSION,
5523
- mode: VALID_MODES.has(input.mode) ? input.mode : "ask",
5556
+ mode: input.mode === "auto" ? "auto" : "ask",
5524
5557
  providerId,
5525
5558
  providerRevision: providerId === "builtin" ? "" : revision.value,
5526
5559
  model: normalizeText(input.model).slice(0, 160),
@@ -5671,7 +5704,10 @@ ${block}`;
5671
5704
  const rawPayload = rawQueueItem?.payload && typeof rawQueueItem.payload === "object" ? rawQueueItem.payload : rawQueueItem;
5672
5705
  const persisted = rawQueueItem?.executionSnapshot || rawPayload?.executionSnapshot;
5673
5706
  if (persisted && typeof persisted === "object") {
5674
- return Codec.normalizeSnapshot(persisted, { source: persisted.source || "submitted" });
5707
+ return Codec.normalizeSnapshot(persisted, {
5708
+ source: persisted.source || "submitted",
5709
+ migrateLegacyConfirm: true
5710
+ });
5675
5711
  }
5676
5712
  const raw = rawPayload && typeof rawPayload === "object" ? rawPayload : {};
5677
5713
  const fallback = fallbackInput && typeof fallbackInput === "object" ? fallbackInput : {};
@@ -5690,12 +5726,16 @@ ${block}`;
5690
5726
  inferred = true;
5691
5727
  }
5692
5728
  return Codec.normalizeSnapshot(captured, {
5693
- source: inferred ? "legacy-inferred" : "legacy-captured"
5729
+ source: inferred ? "legacy-inferred" : "legacy-captured",
5730
+ migrateLegacyConfirm: true
5694
5731
  });
5695
5732
  }
5696
5733
  function resolveForExecution(value = {}, options2 = {}) {
5697
5734
  const persisted = value.executionSnapshot || value;
5698
- const snapshot = Codec.normalizeSnapshot(persisted, { source: persisted.source || "submitted" });
5735
+ const snapshot = Codec.normalizeSnapshot(persisted, {
5736
+ source: persisted.source || "submitted",
5737
+ migrateLegacyConfirm: true
5738
+ });
5699
5739
  if (snapshot.providerId === "builtin") return Codec.normalizeSnapshot(snapshot, { source: snapshot.source });
5700
5740
  const catalog = options2.catalog || {};
5701
5741
  const provider = ProviderProfiles?.getProviderById ? ProviderProfiles.getProviderById(catalog, snapshot.providerId) : (catalog.providers || []).find((item) => item?.id === snapshot.providerId);
@@ -5718,7 +5758,10 @@ ${block}`;
5718
5758
  }
5719
5759
  function snapshotOf(value = {}) {
5720
5760
  const persisted = value.executionSnapshot || value;
5721
- return Codec.normalizeSnapshot(persisted, { source: persisted.source || "submitted" });
5761
+ return Codec.normalizeSnapshot(persisted, {
5762
+ source: persisted.source || "submitted",
5763
+ migrateLegacyConfirm: true
5764
+ });
5722
5765
  }
5723
5766
  function cloneSnapshot(value = {}) {
5724
5767
  const snapshot = snapshotOf(value);
@@ -5836,8 +5879,20 @@ ${block}`;
5836
5879
  }).slice(0, max));
5837
5880
  }
5838
5881
  function normalizeMeta(value) {
5882
+ var revision = normalizeRevision(value && value.revision);
5883
+ var hasDurableRevision = Boolean(value && Object.prototype.hasOwnProperty.call(value, "durableRevision"));
5884
+ var durableRevision = hasDurableRevision ? Math.min(normalizeRevision(value.durableRevision), revision) : revision;
5885
+ var pendingValue = value && value.pendingCommit;
5886
+ var pendingRevision = normalizeRevision(pendingValue && pendingValue.revision);
5887
+ var pendingCommit = pendingValue && typeof pendingValue === "object" && pendingRevision > durableRevision && pendingRevision <= revision ? {
5888
+ revision: pendingRevision,
5889
+ writerId: cleanPart(pendingValue.writerId),
5890
+ startedAt: cleanPart(pendingValue.startedAt)
5891
+ } : null;
5839
5892
  return {
5840
- revision: normalizeRevision(value && value.revision),
5893
+ revision,
5894
+ durableRevision,
5895
+ pendingCommit,
5841
5896
  queueRevision: normalizeRevision(value && value.queueRevision),
5842
5897
  writerId: cleanPart(value && value.writerId),
5843
5898
  updatedAt: cleanPart(value && value.updatedAt),
@@ -6046,19 +6101,78 @@ ${block}`;
6046
6101
  });
6047
6102
  }).call(globalThis, void 0, void 0, void 0);
6048
6103
  (function runClassicContentModule18(module, exports, require2) {
6104
+ (function(root, factory) {
6105
+ if (typeof module === "object" && module.exports) {
6106
+ module.exports = factory();
6107
+ } else {
6108
+ root.CodexOverleafModuleRegistry.define("ScopedPersistenceReceipt", [], factory);
6109
+ }
6110
+ })(typeof globalThis !== "undefined" ? globalThis : this, function() {
6111
+ "use strict";
6112
+ function createFenceMeta(meta, currentMeta, writerId) {
6113
+ var startedAt = (/* @__PURE__ */ new Date()).toISOString();
6114
+ var revision = currentMeta.revision + 1;
6115
+ return {
6116
+ ...meta,
6117
+ revision,
6118
+ durableRevision: currentMeta.durableRevision,
6119
+ pendingCommit: { revision, writerId, startedAt },
6120
+ writerId,
6121
+ updatedAt: startedAt
6122
+ };
6123
+ }
6124
+ function createCommittedMeta(fenceMeta) {
6125
+ return {
6126
+ ...fenceMeta,
6127
+ durableRevision: fenceMeta.revision,
6128
+ pendingCommit: null,
6129
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
6130
+ };
6131
+ }
6132
+ function createRecoveredMeta(currentMeta, fenceMeta, writerId) {
6133
+ var revision = fenceMeta.revision + 1;
6134
+ return {
6135
+ ...currentMeta,
6136
+ revision,
6137
+ durableRevision: revision,
6138
+ pendingCommit: null,
6139
+ queueRevision: fenceMeta.queueRevision + 1,
6140
+ writerId,
6141
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
6142
+ };
6143
+ }
6144
+ function decorateReceiptError(error, revision) {
6145
+ if (error && typeof error === "object") {
6146
+ error.code = error.code || "persistence_receipt_write_failed";
6147
+ error.persistenceActionCommitted = true;
6148
+ error.persistenceRevision = revision;
6149
+ }
6150
+ return error;
6151
+ }
6152
+ return Object.freeze({
6153
+ createFenceMeta,
6154
+ createCommittedMeta,
6155
+ createRecoveredMeta,
6156
+ decorateReceiptError
6157
+ });
6158
+ });
6159
+ }).call(globalThis, void 0, void 0, void 0);
6160
+ (function runClassicContentModule19(module, exports, require2) {
6049
6161
  (function(root, factory) {
6050
6162
  if (typeof module === "object" && module.exports) {
6051
6163
  module.exports = factory(
6052
6164
  require2("./scopedPersistenceQueuePolicy"),
6053
- require2("./scopedPersistenceBrowserAdapter")
6165
+ require2("./scopedPersistenceBrowserAdapter"),
6166
+ require2("./scopedPersistenceReceipt")
6054
6167
  );
6055
6168
  } else {
6056
6169
  root.CodexOverleafModuleRegistry.define("ScopedPersistenceTransaction", [
6057
6170
  "ScopedPersistenceQueuePolicy",
6058
- "ScopedPersistenceBrowserAdapter"
6171
+ "ScopedPersistenceBrowserAdapter",
6172
+ "ScopedPersistenceReceipt"
6059
6173
  ], factory);
6060
6174
  }
6061
- })(typeof globalThis !== "undefined" ? globalThis : this, function(QueuePolicy, BrowserAdapter) {
6175
+ })(typeof globalThis !== "undefined" ? globalThis : this, function(QueuePolicy, BrowserAdapter, Receipt) {
6062
6176
  "use strict";
6063
6177
  var applyQueueMutations = QueuePolicy.applyQueueMutations;
6064
6178
  var cleanPart = QueuePolicy.cleanPart;
@@ -6084,9 +6198,9 @@ ${block}`;
6084
6198
  var scope = normalizeScope(inputScope);
6085
6199
  generation += 1;
6086
6200
  var tokenGeneration = generation;
6087
- active = makeToken(scope, tokenGeneration, 0, false, 0);
6201
+ active = tokenFromMeta(scope, tokenGeneration, false, {});
6088
6202
  var meta = await strictRead(adapter, scope);
6089
- var token = makeToken(scope, tokenGeneration, meta.revision, false, meta.queueRevision);
6203
+ var token = tokenFromMeta(scope, tokenGeneration, false, meta);
6090
6204
  if (active && active.generation === tokenGeneration && sameScope(active, token)) active = token;
6091
6205
  return token;
6092
6206
  }
@@ -6100,10 +6214,10 @@ ${block}`;
6100
6214
  });
6101
6215
  }
6102
6216
  if (!detached && active && sameScope(active, scope)) {
6103
- return makeToken(scope, active.generation, active.revision, false, active.queueRevision);
6217
+ return tokenFromMeta(scope, active.generation, false, active);
6104
6218
  }
6105
6219
  var meta = await strictRead(adapter, scope);
6106
- return makeToken(scope, detached ? 0 : generation, meta.revision, detached, meta.queueRevision);
6220
+ return tokenFromMeta(scope, detached ? 0 : generation, detached, meta);
6107
6221
  }
6108
6222
  function isCurrent(token) {
6109
6223
  return Boolean(token && active && token.detached !== true && token.generation === active.generation && sameScope(token, active));
@@ -6130,13 +6244,7 @@ ${block}`;
6130
6244
  var queueMutations = normalizeQueueMutations(commitOptions);
6131
6245
  if (queueMutations.length && currentMeta.queueRevision !== normalizeRevision(token.queueRevision)) {
6132
6246
  if (!token.detached && isCurrent(token)) {
6133
- active = makeToken(
6134
- scope,
6135
- token.generation,
6136
- currentMeta.revision,
6137
- false,
6138
- currentMeta.queueRevision
6139
- );
6247
+ active = tokenFromMeta(scope, token.generation, false, currentMeta);
6140
6248
  }
6141
6249
  return {
6142
6250
  ok: false,
@@ -6148,33 +6256,26 @@ ${block}`;
6148
6256
  }
6149
6257
  var projected = applyQueueMutations(currentMeta, queueMutations, writerId);
6150
6258
  if (!projected.ok) return projected;
6151
- var nextMeta = {
6259
+ var nextMeta = Receipt.createFenceMeta({
6152
6260
  ...projected.meta,
6153
- revision: currentMeta.revision + 1,
6154
- writerId,
6155
- updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
6156
6261
  sessionTombstones: mergeTombstones(
6157
6262
  projected.meta.sessionTombstones,
6158
6263
  commitOptions && commitOptions.sessionTombstones,
6159
6264
  200
6160
6265
  )
6161
- };
6266
+ }, currentMeta, writerId);
6162
6267
  await adapter.write(scope, nextMeta);
6163
6268
  if (!token.detached && isCurrent(token)) {
6164
- active = makeToken(
6165
- scope,
6166
- token.generation,
6167
- nextMeta.revision,
6168
- false,
6169
- nextMeta.queueRevision
6170
- );
6269
+ active = tokenFromMeta(scope, token.generation, false, nextMeta);
6171
6270
  }
6172
6271
  var value;
6173
6272
  try {
6174
6273
  value = await action({
6175
6274
  scope,
6176
6275
  baseRevision: currentMeta.revision,
6276
+ durableRevision: currentMeta.durableRevision,
6177
6277
  conflict,
6278
+ previousCommitIncomplete: Boolean(currentMeta.pendingCommit),
6178
6279
  writerId,
6179
6280
  currentMeta,
6180
6281
  nextMeta
@@ -6183,23 +6284,11 @@ ${block}`;
6183
6284
  if (queueMutations.some(function(mutation) {
6184
6285
  return ["remove", "release", "restore"].includes(cleanPart(mutation.type));
6185
6286
  })) {
6186
- var recoveredMeta = {
6187
- ...currentMeta,
6188
- revision: nextMeta.revision + 1,
6189
- queueRevision: nextMeta.queueRevision + 1,
6190
- writerId,
6191
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
6192
- };
6287
+ var recoveredMeta = Receipt.createRecoveredMeta(currentMeta, nextMeta, writerId);
6193
6288
  try {
6194
6289
  await adapter.write(scope, recoveredMeta);
6195
6290
  if (!token.detached && isCurrent(token)) {
6196
- active = makeToken(
6197
- scope,
6198
- token.generation,
6199
- recoveredMeta.revision,
6200
- false,
6201
- recoveredMeta.queueRevision
6202
- );
6291
+ active = tokenFromMeta(scope, token.generation, false, recoveredMeta);
6203
6292
  }
6204
6293
  } catch (recoveryError) {
6205
6294
  if (error && typeof error === "object") {
@@ -6209,13 +6298,24 @@ ${block}`;
6209
6298
  }
6210
6299
  throw error;
6211
6300
  }
6301
+ var committedMeta = Receipt.createCommittedMeta(nextMeta);
6302
+ try {
6303
+ await adapter.write(scope, committedMeta);
6304
+ } catch (error) {
6305
+ throw Receipt.decorateReceiptError(error, nextMeta.revision);
6306
+ }
6307
+ if (!token.detached && isCurrent(token)) {
6308
+ active = tokenFromMeta(scope, token.generation, false, committedMeta);
6309
+ }
6212
6310
  return {
6213
6311
  ok: true,
6214
6312
  value,
6215
- revision: nextMeta.revision,
6216
- queueRevision: nextMeta.queueRevision,
6217
- queueClaims: nextMeta.queueClaims,
6313
+ revision: committedMeta.revision,
6314
+ durableRevision: committedMeta.durableRevision,
6315
+ queueRevision: committedMeta.queueRevision,
6316
+ queueClaims: committedMeta.queueClaims,
6218
6317
  rebased: conflict,
6318
+ recoveredIncompleteCommit: Boolean(currentMeta.pendingCommit),
6219
6319
  superseded: !token.detached && !isCurrent(token)
6220
6320
  };
6221
6321
  });
@@ -6225,7 +6325,7 @@ ${block}`;
6225
6325
  captureCommitView,
6226
6326
  commit,
6227
6327
  getActiveView: function() {
6228
- return active ? makeToken(active, active.generation, active.revision, false, active.queueRevision) : null;
6328
+ return active ? tokenFromMeta(active, active.generation, false, active) : null;
6229
6329
  },
6230
6330
  getWriterId: function() {
6231
6331
  return writerId;
@@ -6237,16 +6337,29 @@ ${block}`;
6237
6337
  isCurrent
6238
6338
  });
6239
6339
  }
6240
- function makeToken(scope, tokenGeneration, revision, detached, queueRevision) {
6340
+ function makeToken(scope, tokenGeneration, revision, detached, queueRevision, durableRevision, pendingCommit) {
6241
6341
  return Object.freeze({
6242
6342
  accountScopeId: scope.accountScopeId,
6243
6343
  projectId: scope.projectId,
6244
6344
  generation: normalizeRevision(tokenGeneration),
6245
6345
  revision: normalizeRevision(revision),
6346
+ durableRevision: normalizeRevision(durableRevision),
6347
+ pendingCommit: pendingCommit && typeof pendingCommit === "object" ? Object.freeze({ ...pendingCommit }) : null,
6246
6348
  queueRevision: normalizeRevision(queueRevision),
6247
6349
  detached: detached === true
6248
6350
  });
6249
6351
  }
6352
+ function tokenFromMeta(scope, tokenGeneration, detached, meta) {
6353
+ return makeToken(
6354
+ scope,
6355
+ tokenGeneration,
6356
+ meta.revision,
6357
+ detached,
6358
+ meta.queueRevision,
6359
+ meta.durableRevision,
6360
+ meta.pendingCommit
6361
+ );
6362
+ }
6250
6363
  async function strictRead(adapter, scope) {
6251
6364
  return normalizeMeta(await adapter.read(scope));
6252
6365
  }
@@ -6268,7 +6381,7 @@ ${block}`;
6268
6381
  });
6269
6382
  });
6270
6383
  }).call(globalThis, void 0, void 0, void 0);
6271
- (function runClassicContentModule19(module, exports, require2) {
6384
+ (function runClassicContentModule20(module, exports, require2) {
6272
6385
  (function initCodexOverleafRunInputQueue(root, factory) {
6273
6386
  if (typeof module === "object" && module.exports) {
6274
6387
  module.exports = factory(require2("./runExecutionSnapshot"));
@@ -6538,7 +6651,7 @@ ${block}`;
6538
6651
  };
6539
6652
  });
6540
6653
  }).call(globalThis, void 0, void 0, void 0);
6541
- (function runClassicContentModule20(module, exports, require2) {
6654
+ (function runClassicContentModule21(module, exports, require2) {
6542
6655
  (function initCodexOverleafSettlementFacts(root, factory) {
6543
6656
  if (typeof module === "object" && module.exports) {
6544
6657
  module.exports = factory(require2("./failureReasons"));
@@ -6830,7 +6943,7 @@ ${block}`;
6830
6943
  };
6831
6944
  });
6832
6945
  }).call(globalThis, void 0, void 0, void 0);
6833
- (function runClassicContentModule21(module, exports, require2) {
6946
+ (function runClassicContentModule22(module, exports, require2) {
6834
6947
  (function initCodexOverleafWritebackEvidenceProjection(root, factory) {
6835
6948
  const api = factory();
6836
6949
  if (typeof module === "object" && module.exports) module.exports = api;
@@ -6963,7 +7076,7 @@ ${block}`;
6963
7076
  });
6964
7077
  });
6965
7078
  }).call(globalThis, void 0, void 0, void 0);
6966
- (function runClassicContentModule22(module, exports, require2) {
7079
+ (function runClassicContentModule23(module, exports, require2) {
6967
7080
  (function initCodexOverleafWritebackOperationEvidence(root, factory) {
6968
7081
  if (typeof module === "object" && module.exports) {
6969
7082
  module.exports = factory();
@@ -7068,12 +7181,22 @@ ${block}`;
7068
7181
  };
7069
7182
  }
7070
7183
  function normalizeTrackedChanges(value) {
7071
- return (Array.isArray(value) ? value : []).map((item) => ({
7072
- key: normalizeText(item?.key),
7073
- id: normalizeText(item?.id),
7074
- path: normalizeText(item?.path),
7075
- label: normalizeText(item?.label)
7076
- })).filter((item) => item.key || item.id || item.path);
7184
+ const normalized = [];
7185
+ const seen = /* @__PURE__ */ new Set();
7186
+ for (const item of Array.isArray(value) ? value : []) {
7187
+ const change = {
7188
+ key: normalizeText(item?.key),
7189
+ id: normalizeText(item?.id),
7190
+ path: normalizeText(item?.path),
7191
+ label: normalizeText(item?.label)
7192
+ };
7193
+ if (!change.key && !change.id && !change.path) continue;
7194
+ const identity = `${change.path}\0${change.key || change.id || "path-only"}`;
7195
+ if (seen.has(identity)) continue;
7196
+ seen.add(identity);
7197
+ normalized.push(change);
7198
+ }
7199
+ return normalized;
7077
7200
  }
7078
7201
  function normalizeStringArray(value) {
7079
7202
  return (Array.isArray(value) ? value : []).map(normalizeText).filter(Boolean);
@@ -7092,7 +7215,7 @@ ${block}`;
7092
7215
  };
7093
7216
  });
7094
7217
  }).call(globalThis, void 0, void 0, void 0);
7095
- (function runClassicContentModule23(module, exports, require2) {
7218
+ (function runClassicContentModule24(module, exports, require2) {
7096
7219
  (function initCodexOverleafWritebackSettlement(root, factory) {
7097
7220
  if (typeof module === "object" && module.exports) {
7098
7221
  module.exports = factory(
@@ -7351,7 +7474,8 @@ ${block}`;
7351
7474
  }
7352
7475
  const successful = isSuccessfulTrackedChangeSettlement(input.result);
7353
7476
  const reviewCodes = kind === "accept" ? ACCEPT_NEEDS_REVIEW_CODES : REJECT_NEEDS_REVIEW_CODES;
7354
- const needsReview = !successful && failures.some(
7477
+ const incompleteReject = kind === "reject" && collectRunResultSkipped(input.result).length > 0;
7478
+ const needsReview = incompleteReject || !successful && failures.some(
7355
7479
  (failure) => failure.terminalState === "needs_review" || reviewCodes.has(failure.code)
7356
7480
  );
7357
7481
  const status = needsReview ? "needs_review" : kind === "accept" ? "accepted" : "rejected";
@@ -7610,7 +7734,7 @@ ${block}`;
7610
7734
  if (!operation || typeof operation !== "object") return operation;
7611
7735
  return operation.type === "edit" && typeof result?.verifiedContent === "string" ? { ...operation, verifiedContent: result.verifiedContent } : operation;
7612
7736
  }
7613
- function selectExpectedFilesForTrackedUndo(project, operations = [], trackedChanges = []) {
7737
+ function selectExpectedFilesForTrackedUndo(project, operations = [], trackedChanges = [], previousExpectedFiles = []) {
7614
7738
  const paths = /* @__PURE__ */ new Set();
7615
7739
  for (const change of trackedChanges || []) {
7616
7740
  if (change?.path) paths.add(change.path);
@@ -7619,7 +7743,18 @@ ${block}`;
7619
7743
  if (operation?.path) paths.add(operation.path);
7620
7744
  if (operation?.to) paths.add(operation.to);
7621
7745
  }
7622
- return (project?.files || []).filter((file) => paths.has(file.path) && typeof file.content === "string").map((file) => ({ path: file.path, content: file.content }));
7746
+ const expectedByPath = /* @__PURE__ */ new Map();
7747
+ for (const file of previousExpectedFiles || []) {
7748
+ if (paths.has(file?.path) && typeof file?.content === "string" && !expectedByPath.has(file.path)) {
7749
+ expectedByPath.set(file.path, { path: file.path, content: file.content });
7750
+ }
7751
+ }
7752
+ for (const file of project?.files || []) {
7753
+ if (paths.has(file?.path) && typeof file?.content === "string" && !expectedByPath.has(file.path)) {
7754
+ expectedByPath.set(file.path, { path: file.path, content: file.content });
7755
+ }
7756
+ }
7757
+ return Array.from(expectedByPath.values());
7623
7758
  }
7624
7759
  function acceptDiagnosticStatus(step, info) {
7625
7760
  if (step === "modeBefore" || step === "replayStart") return "info";
@@ -7703,7 +7838,7 @@ ${block}`;
7703
7838
  };
7704
7839
  });
7705
7840
  }).call(globalThis, void 0, void 0, void 0);
7706
- (function runClassicContentModule24(module, exports, require2) {
7841
+ (function runClassicContentModule25(module, exports, require2) {
7707
7842
  (function initSessionState(root, factory) {
7708
7843
  if (typeof module === "object" && module.exports) {
7709
7844
  module.exports = factory(
@@ -7723,7 +7858,7 @@ ${block}`;
7723
7858
  })(typeof globalThis !== "undefined" ? globalThis : window, function sessionStateFactory(i18n, SettlementFacts, RunInputQueue, LineReferences, PathRedaction) {
7724
7859
  "use strict";
7725
7860
  const DEFAULT_PANEL_STATE = {
7726
- mode: "confirm",
7861
+ mode: "ask",
7727
7862
  providerId: "builtin",
7728
7863
  model: "gpt-5.4",
7729
7864
  reasoningEffort: "high",
@@ -7745,8 +7880,8 @@ ${block}`;
7745
7880
  activeSessionId: "",
7746
7881
  customInstructionsByProject: {}
7747
7882
  };
7748
- const VALID_MODES = /* @__PURE__ */ new Set(["ask", "confirm", "auto"]);
7749
- const VALID_REASONING = /* @__PURE__ */ new Set(["none", "minimal", "low", "medium", "high", "xhigh"]);
7883
+ const VALID_MODES = /* @__PURE__ */ new Set(["ask", "auto"]);
7884
+ const VALID_REASONING = /* @__PURE__ */ new Set(["none", "minimal", "low", "medium", "high", "xhigh", "max", "ultra"]);
7750
7885
  const VALID_SPEED_TIERS = /* @__PURE__ */ new Set(["standard", "fast"]);
7751
7886
  const VALID_LOCALES = /* @__PURE__ */ new Set(["en", "zh"]);
7752
7887
  const VALID_EVENT_STATUSES = /* @__PURE__ */ new Set(["info", "running", "completed", "failed", "warning", "blocked", "skipped", "pending"]);
@@ -7814,12 +7949,8 @@ ${block}`;
7814
7949
  ...DEFAULT_PANEL_STATE,
7815
7950
  ...input
7816
7951
  };
7817
- if (!VALID_MODES.has(state.mode)) {
7818
- state.mode = DEFAULT_PANEL_STATE.mode;
7819
- }
7820
- if (!VALID_REASONING.has(state.reasoningEffort)) {
7821
- state.reasoningEffort = DEFAULT_PANEL_STATE.reasoningEffort;
7822
- }
7952
+ state.mode = normalizeMode(state.mode);
7953
+ state.reasoningEffort = normalizeReasoning(state.reasoningEffort);
7823
7954
  if (!VALID_SPEED_TIERS.has(state.speedTier)) {
7824
7955
  state.speedTier = DEFAULT_PANEL_STATE.speedTier;
7825
7956
  }
@@ -7892,14 +8023,17 @@ ${block}`;
7892
8023
  history,
7893
8024
  runs,
7894
8025
  task: sanitizeAssistantVisibleText(session.task),
7895
- mode: VALID_MODES.has(session.mode) ? session.mode : fallbackState.mode,
8026
+ mode: normalizeMode(session.mode, fallbackState.mode),
7896
8027
  providerId: typeof session.providerId === "string" && session.providerId.trim() ? session.providerId.trim() : fallbackState.providerId || "builtin",
7897
8028
  model: typeof session.model === "string" && session.model ? session.model : fallbackState.model,
7898
8029
  reasoningEffort: VALID_REASONING.has(session.reasoningEffort) ? session.reasoningEffort : fallbackState.reasoningEffort,
7899
8030
  speedTier: VALID_SPEED_TIERS.has(session.speedTier) ? session.speedTier : fallbackState.speedTier,
7900
8031
  requireReviewing: session.requireReviewing !== false,
7901
8032
  focusFiles: normalizeFocusFiles(session.focusFiles),
8033
+ projectReferenceFiles: normalizeProjectReferenceFiles(session.projectReferenceFiles),
7902
8034
  codexThreadId: typeof session.codexThreadId === "string" ? session.codexThreadId : "",
8035
+ forkedFromSessionId: typeof session.forkedFromSessionId === "string" ? session.forkedFromSessionId : "",
8036
+ forkedFromRunId: typeof session.forkedFromRunId === "string" ? session.forkedFromRunId : "",
7903
8037
  pendingInputs: normalizePendingInputs(
7904
8038
  session.pendingInputs,
7905
8039
  options2.restoreRunningRuns === true,
@@ -7968,13 +8102,14 @@ ${block}`;
7968
8102
  id: active.id,
7969
8103
  history: Array.isArray(active.history) ? active.history.slice(-10) : [],
7970
8104
  focusFiles: normalizeFocusFiles(active.focusFiles),
8105
+ projectReferenceFiles: normalizeProjectReferenceFiles(active.projectReferenceFiles),
7971
8106
  codexThreadId: active.codexThreadId || "",
7972
8107
  providerId: state.providerId || "builtin"
7973
8108
  };
7974
8109
  state.runs = Array.isArray(active.runs) ? active.runs : [];
7975
8110
  state.task = typeof active.task === "string" ? active.task : "";
7976
8111
  state.focusFiles = normalizeFocusFiles(active.focusFiles);
7977
- state.mode = VALID_MODES.has(active.mode) ? active.mode : DEFAULT_PANEL_STATE.mode;
8112
+ state.mode = normalizeMode(active.mode);
7978
8113
  state.requireReviewing = active.requireReviewing !== false;
7979
8114
  return state;
7980
8115
  }
@@ -7992,14 +8127,17 @@ ${block}`;
7992
8127
  history: normalizeHistoryEntries(overrides.history),
7993
8128
  runs,
7994
8129
  task: sanitizeAssistantVisibleText(overrides.task),
7995
- mode: VALID_MODES.has(overrides.mode) ? overrides.mode : DEFAULT_PANEL_STATE.mode,
8130
+ mode: normalizeMode(overrides.mode),
7996
8131
  providerId: typeof overrides.providerId === "string" && overrides.providerId.trim() ? overrides.providerId.trim() : "builtin",
7997
8132
  model: typeof overrides.model === "string" && overrides.model ? overrides.model : DEFAULT_PANEL_STATE.model,
7998
8133
  reasoningEffort: VALID_REASONING.has(overrides.reasoningEffort) ? overrides.reasoningEffort : DEFAULT_PANEL_STATE.reasoningEffort,
7999
8134
  speedTier: VALID_SPEED_TIERS.has(overrides.speedTier) ? overrides.speedTier : DEFAULT_PANEL_STATE.speedTier,
8000
8135
  requireReviewing: overrides.requireReviewing !== false,
8001
8136
  focusFiles: normalizeFocusFiles(overrides.focusFiles),
8137
+ projectReferenceFiles: normalizeProjectReferenceFiles(overrides.projectReferenceFiles),
8002
8138
  codexThreadId: typeof overrides.codexThreadId === "string" ? overrides.codexThreadId : "",
8139
+ forkedFromSessionId: typeof overrides.forkedFromSessionId === "string" ? overrides.forkedFromSessionId : "",
8140
+ forkedFromRunId: typeof overrides.forkedFromRunId === "string" ? overrides.forkedFromRunId : "",
8003
8141
  pendingInputs: normalizePendingInputs(overrides.pendingInputs)
8004
8142
  };
8005
8143
  }
@@ -8231,6 +8369,8 @@ ${block}`;
8231
8369
  undoStatus: sanitizeAssistantVisibleText(run.undoStatus),
8232
8370
  nativeRequestId: sanitizeAssistantVisibleText(run.nativeRequestId),
8233
8371
  codexTurnId: sanitizeAssistantVisibleText(run.codexTurnId),
8372
+ forkSnapshot: run.forkSnapshot === true,
8373
+ forkSourceRunId: sanitizeAssistantVisibleText(run.forkSourceRunId),
8234
8374
  nativeEventSeq: Number.isFinite(Number(run.nativeEventSeq)) ? Number(run.nativeEventSeq) : 0,
8235
8375
  queueItemId: sanitizeAssistantVisibleText(run.queueItemId),
8236
8376
  interruptedDraft: run.interruptedDraft ? sanitizeAssistantVisibleValue(run.interruptedDraft) : void 0
@@ -8418,6 +8558,32 @@ ${block}`;
8418
8558
  }
8419
8559
  return files.slice(0, 5);
8420
8560
  }
8561
+ function normalizeProjectReferenceFiles(value) {
8562
+ const seen = /* @__PURE__ */ new Set();
8563
+ const files = [];
8564
+ for (const item of Array.isArray(value) ? value : []) {
8565
+ const rawPath = typeof item === "string" ? item : item?.path;
8566
+ if (typeof rawPath !== "string" || !rawPath.trim() || rawPath.length > 512) {
8567
+ continue;
8568
+ }
8569
+ if (/^(?:[A-Za-z]:|[\\/])/.test(rawPath) || rawPath.includes("\0")) {
8570
+ continue;
8571
+ }
8572
+ const path = rawPath.replace(/\\/g, "/").replace(/\/+/g, "/").replace(/^\.\//, "").trim();
8573
+ if (!path || path.split("/").some((segment) => !segment || segment === "." || segment === "..") || seen.has(path)) {
8574
+ continue;
8575
+ }
8576
+ seen.add(path);
8577
+ files.push({
8578
+ path,
8579
+ kind: item?.kind === "binary" ? "binary" : "text"
8580
+ });
8581
+ if (files.length >= 5e3) {
8582
+ break;
8583
+ }
8584
+ }
8585
+ return files;
8586
+ }
8421
8587
  function normalizeCustomInstructionsByProject(value) {
8422
8588
  const result = {};
8423
8589
  if (!value || typeof value !== "object" || Array.isArray(value)) {
@@ -8491,7 +8657,7 @@ ${block}`;
8491
8657
  // Skills page was reopened.
8492
8658
  codexOverleafSkills: compactCodexOverleafSkillsForStorage(source.codexOverleafSkills),
8493
8659
  composerAttachments: normalizeComposerAttachmentsForPersistence(source.composerAttachments),
8494
- mode: VALID_MODES.has(active?.mode) ? active.mode : normalizeMode(source.mode),
8660
+ mode: normalizeMode(active?.mode, source.mode),
8495
8661
  providerId: typeof source.providerId === "string" && source.providerId.trim() ? source.providerId.trim() : "builtin",
8496
8662
  model: normalizeTextField(source.model || DEFAULT_PANEL_STATE.model, 80),
8497
8663
  reasoningEffort: VALID_REASONING.has(source.reasoningEffort) ? source.reasoningEffort : normalizeReasoning(source.reasoningEffort),
@@ -8578,7 +8744,10 @@ ${block}`;
8578
8744
  speedTier: normalizeSpeedTier(session.speedTier || fallbackState.speedTier),
8579
8745
  requireReviewing: session.requireReviewing !== false,
8580
8746
  focusFiles: normalizeFocusFiles(session.focusFiles),
8747
+ projectReferenceFiles: normalizeProjectReferenceFiles(session.projectReferenceFiles),
8581
8748
  codexThreadId: typeof session.codexThreadId === "string" ? session.codexThreadId : "",
8749
+ forkedFromSessionId: normalizeTextField(session.forkedFromSessionId, 160),
8750
+ forkedFromRunId: normalizeTextField(session.forkedFromRunId, 160),
8582
8751
  pendingInputs: normalizePendingInputs(session.pendingInputs)
8583
8752
  };
8584
8753
  if (typeof session.lastActivityAt === "string" && session.lastActivityAt) {
@@ -8651,6 +8820,8 @@ ${block}`;
8651
8820
  undoStatus: summarizeTextForStorage(run.undoStatus, "undo status"),
8652
8821
  nativeRequestId: normalizeTextField(run.nativeRequestId, 160),
8653
8822
  codexTurnId: normalizeTextField(run.codexTurnId, 160),
8823
+ forkSnapshot: run.forkSnapshot === true,
8824
+ forkSourceRunId: normalizeTextField(run.forkSourceRunId, 160),
8654
8825
  nativeEventSeq: Number.isFinite(Number(run.nativeEventSeq)) ? Number(run.nativeEventSeq) : 0,
8655
8826
  queueItemId: normalizeTextField(run.queueItemId, 160)
8656
8827
  };
@@ -8785,8 +8956,14 @@ ${block}`;
8785
8956
  undoExpectedFiles: []
8786
8957
  };
8787
8958
  }
8788
- function normalizeMode(mode) {
8789
- return VALID_MODES.has(mode) ? mode : DEFAULT_PANEL_STATE.mode;
8959
+ function normalizeMode(mode, fallback = DEFAULT_PANEL_STATE.mode) {
8960
+ if (mode === "confirm") {
8961
+ return "ask";
8962
+ }
8963
+ if (VALID_MODES.has(mode)) {
8964
+ return mode;
8965
+ }
8966
+ return VALID_MODES.has(fallback) ? fallback : DEFAULT_PANEL_STATE.mode;
8790
8967
  }
8791
8968
  function normalizeReasoning(reasoningEffort) {
8792
8969
  return VALID_REASONING.has(reasoningEffort) ? reasoningEffort : DEFAULT_PANEL_STATE.reasoningEffort;
@@ -8980,7 +9157,7 @@ ${block}`;
8980
9157
  };
8981
9158
  });
8982
9159
  }).call(globalThis, void 0, void 0, void 0);
8983
- (function runClassicContentModule25(module, exports, require2) {
9160
+ (function runClassicContentModule26(module, exports, require2) {
8984
9161
  (function initStorageKeys(root, factory) {
8985
9162
  if (typeof module === "object" && module.exports) {
8986
9163
  module.exports = factory();
@@ -9008,7 +9185,7 @@ ${block}`;
9008
9185
  };
9009
9186
  });
9010
9187
  }).call(globalThis, void 0, void 0, void 0);
9011
- (function runClassicContentModule26(module, exports, require2) {
9188
+ (function runClassicContentModule27(module, exports, require2) {
9012
9189
  (function initStaleGuard(root, factory) {
9013
9190
  if (typeof module === "object" && module.exports) {
9014
9191
  module.exports = factory();
@@ -9159,7 +9336,7 @@ ${block}`;
9159
9336
  };
9160
9337
  });
9161
9338
  }).call(globalThis, void 0, void 0, void 0);
9162
- (function runClassicContentModule27(module, exports, require2) {
9339
+ (function runClassicContentModule28(module, exports, require2) {
9163
9340
  (function initStorageRunActions(root, factory) {
9164
9341
  if (typeof module === "object" && module.exports) {
9165
9342
  module.exports = factory();
@@ -9192,8 +9369,9 @@ ${block}`;
9192
9369
  function hasReloadableRunActionPayload(run) {
9193
9370
  var trackedStatus = run && run.trackedChangeStatus;
9194
9371
  var trackedLifecycle = (trackedStatus === "pending" || trackedStatus === "needs_review") && Array.isArray(run.undoTrackedChanges) && run.undoTrackedChanges.length > 0 && Array.isArray(run.undoExpectedFiles) && run.undoExpectedFiles.length > 0 && Array.isArray(run.appliedOperations) && run.appliedOperations.length > 0;
9372
+ var reviewingEditorUndo = trackedStatus !== "accepted" && trackedStatus !== "rejected" && run && run.undoStatus !== "applied" && run.executionSnapshot && run.executionSnapshot.requireReviewing === true && Array.isArray(run.undoExpectedFiles) && run.undoExpectedFiles.length > 0 && Array.isArray(run.appliedOperations) && run.appliedOperations.length > 0;
9195
9373
  var legacyUndo = Array.isArray(run && run.undoOperations) && run.undoOperations.length > 0;
9196
- return trackedLifecycle || legacyUndo;
9374
+ return trackedLifecycle || reviewingEditorUndo || legacyUndo;
9197
9375
  }
9198
9376
  function compactRunActionPayload(run, keepActionPayload) {
9199
9377
  var empty = emptyActionPayload();
@@ -9287,7 +9465,7 @@ ${block}`;
9287
9465
  };
9288
9466
  });
9289
9467
  }).call(globalThis, void 0, void 0, void 0);
9290
- (function runClassicContentModule28(module, exports, require2) {
9468
+ (function runClassicContentModule29(module, exports, require2) {
9291
9469
  (function initStorageSessionClaims(root, factory) {
9292
9470
  var api = factory();
9293
9471
  if (typeof module === "object" && module.exports) module.exports = api;
@@ -9353,7 +9531,7 @@ ${block}`;
9353
9531
  return Object.freeze({ createSessionClaimer });
9354
9532
  });
9355
9533
  }).call(globalThis, void 0, void 0, void 0);
9356
- (function runClassicContentModule29(module, exports, require2) {
9534
+ (function runClassicContentModule30(module, exports, require2) {
9357
9535
  (function initStorageDb(root, factory) {
9358
9536
  if (typeof module === "object" && module.exports) {
9359
9537
  module.exports = factory(
@@ -9648,7 +9826,7 @@ ${block}`;
9648
9826
  history: compactHistoryForStorage(input.history),
9649
9827
  runs: compactRunsForStorage(input.runs, options2),
9650
9828
  task: normalizeDisplayTextForStorage(input.task, SESSION_STORAGE_LIMITS.taskChars),
9651
- mode: typeof input.mode === "string" ? input.mode : "",
9829
+ mode: normalizeCurrentMode(input.mode),
9652
9830
  providerId: typeof input.providerId === "string" && input.providerId ? input.providerId : "builtin",
9653
9831
  model: typeof input.model === "string" ? input.model : "",
9654
9832
  reasoningEffort: typeof input.reasoningEffort === "string" ? input.reasoningEffort : "",
@@ -9779,6 +9957,9 @@ ${block}`;
9779
9957
  saveVerification: input.saveVerification && typeof input.saveVerification === "object" ? summarizeVerificationObject(input.saveVerification) : null
9780
9958
  };
9781
9959
  }
9960
+ function normalizeCurrentMode(mode) {
9961
+ return mode === "auto" ? "auto" : "ask";
9962
+ }
9782
9963
  function extractLightweightPrefs(state, projectId) {
9783
9964
  var prefs = {
9784
9965
  storageSchemaVersion: TARGET_SCHEMA_VERSION,
@@ -9786,8 +9967,9 @@ ${block}`;
9786
9967
  model: typeof state.model === "string" ? state.model : "",
9787
9968
  reasoningEffort: typeof state.reasoningEffort === "string" ? state.reasoningEffort : "",
9788
9969
  speedTier: typeof state.speedTier === "string" ? state.speedTier : "",
9789
- mode: typeof state.mode === "string" ? state.mode : "",
9970
+ mode: normalizeCurrentMode(state.mode),
9790
9971
  locale: typeof state.locale === "string" ? state.locale : "",
9972
+ theme: state.theme === "light" || state.theme === "auto" ? state.theme : "dark",
9791
9973
  requireReviewing: state.requireReviewing !== false,
9792
9974
  autoRecompile: state.autoRecompile !== false,
9793
9975
  loadCodexLocalSkills: state.loadCodexLocalSkills !== false,
@@ -10574,7 +10756,7 @@ ${block}`;
10574
10756
  };
10575
10757
  });
10576
10758
  }).call(globalThis, void 0, void 0, void 0);
10577
- (function runClassicContentModule30(module, exports, require2) {
10759
+ (function runClassicContentModule31(module, exports, require2) {
10578
10760
  (function initStorageMigration(root, factory) {
10579
10761
  if (typeof module === "object" && module.exports) {
10580
10762
  module.exports = factory(require2("./storageDb"));
@@ -11029,7 +11211,7 @@ ${block}`;
11029
11211
  };
11030
11212
  });
11031
11213
  }).call(globalThis, void 0, void 0, void 0);
11032
- (function runClassicContentModule31(module, exports, require2) {
11214
+ (function runClassicContentModule32(module, exports, require2) {
11033
11215
  (function initCompileAdapter(root, factory) {
11034
11216
  if (typeof module === "object" && module.exports) {
11035
11217
  module.exports = factory();
@@ -11172,7 +11354,7 @@ ${block}`;
11172
11354
  };
11173
11355
  });
11174
11356
  }).call(globalThis, void 0, void 0, void 0);
11175
- (function runClassicContentModule32(module, exports, require2) {
11357
+ (function runClassicContentModule33(module, exports, require2) {
11176
11358
  (function initCodexOverleafCompatibility(root, factory) {
11177
11359
  if (typeof module === "object" && module.exports) {
11178
11360
  module.exports = factory();
@@ -11186,7 +11368,7 @@ ${block}`;
11186
11368
  const MIN_NATIVE_VERSION = "1.0.0";
11187
11369
  const MIN_COMPATIBLE_NATIVE_VERSION = "1.0.0";
11188
11370
  const MIN_COMPATIBLE_EXTENSION_VERSION = "1.0.0";
11189
- const BUILD_TARGET_VERSION = "2.3.0";
11371
+ const BUILD_TARGET_VERSION = "2.3.2";
11190
11372
  const DEFAULT_CHROME_EXTENSION_ID = "illdpneeeopfffmiepaejglgmhpmdhdc";
11191
11373
  const REQUIRED_CAPABILITIES = Object.freeze([
11192
11374
  "bridgePing",
@@ -11200,7 +11382,9 @@ ${block}`;
11200
11382
  "historyClearPlugin",
11201
11383
  "localSkills",
11202
11384
  "mirrorSensitiveScan",
11203
- "providerProfiles"
11385
+ "providerProfiles",
11386
+ "assetTransfer",
11387
+ "threadFork"
11204
11388
  ]);
11205
11389
  const UPDATE_AVAILABLE_CAPABILITIES = Object.freeze([
11206
11390
  "bridgePing",
@@ -11480,14 +11664,14 @@ ${block}`;
11480
11664
  };
11481
11665
  });
11482
11666
  }).call(globalThis, void 0, void 0, void 0);
11483
- (function runClassicContentModule33(module, exports, require2) {
11667
+ (function runClassicContentModule34(module, exports, require2) {
11484
11668
  (function(root, factory) {
11485
11669
  var api = factory();
11486
11670
  if (typeof module === "object" && module.exports) module.exports = api;
11487
11671
  if (root) root.CodexOverleafPageRpcContract = api;
11488
11672
  })(typeof window !== "undefined" ? window : typeof globalThis !== "undefined" ? globalThis : this, function() {
11489
11673
  "use strict";
11490
- var REVISION = "2026-07-26-page-rpc-contract-v13";
11674
+ var REVISION = "2026-08-04-page-rpc-contract-v15";
11491
11675
  var METHODS = freezeCatalog({
11492
11676
  initializeCapability: entry("bridge.initialize", "control", "none", "default", false, "none"),
11493
11677
  probe: entry("bridge.probe", "read", "none", "default", false, "safe"),
@@ -11499,6 +11683,10 @@ ${block}`;
11499
11683
  ensureReviewing: entry("reviewing.enable", "page_state", "optional", "default", true, "idempotent"),
11500
11684
  ensureEditing: entry("reviewing.disable", "page_state", "optional", "default", true, "idempotent"),
11501
11685
  applyOperations: entry("document.write", "document", "required", "writeback", true, "no_retry"),
11686
+ binaryUploadBegin: entry("asset.stage", "cache", "required", "default", false, "no_retry"),
11687
+ binaryUploadAppend: entry("asset.stage", "cache", "none", "writeback", true, "no_retry"),
11688
+ binaryUploadCommit: entry("asset.write", "document", "required", "writeback", true, "no_retry"),
11689
+ binaryUploadAbort: entry("asset.stage", "cache", "none", "default", false, "idempotent"),
11502
11690
  jumpToPosition: entry("editor.navigate", "navigation", "required", "default", false, "idempotent"),
11503
11691
  rejectTrackedChanges: entry("tracked_changes.reject", "document", "required", "lifecycle", true, "no_retry"),
11504
11692
  acceptTrackedChanges: entry("tracked_changes.accept", "document", "required", "lifecycle", true, "no_retry"),
@@ -11543,7 +11731,7 @@ ${block}`;
11543
11731
  file_list: 35e3,
11544
11732
  compile: 75e3,
11545
11733
  lifecycle: 12e4,
11546
- writeback: 3e4
11734
+ writeback: 45e3
11547
11735
  };
11548
11736
  var candidate = Number(overrides[timeoutClass]);
11549
11737
  return Number.isFinite(candidate) && candidate > 0 ? candidate : defaults[timeoutClass];
@@ -11607,7 +11795,7 @@ ${block}`;
11607
11795
  });
11608
11796
  });
11609
11797
  }).call(globalThis, void 0, void 0, void 0);
11610
- (function runClassicContentModule34(module, exports, require2) {
11798
+ (function runClassicContentModule35(module, exports, require2) {
11611
11799
  (function initCodexOverleafManagedUpdateProjection(root) {
11612
11800
  "use strict";
11613
11801
  const PHASE_ALIASES = Object.freeze({
@@ -11913,7 +12101,7 @@ ${block}`;
11913
12101
  });
11914
12102
  })(typeof window !== "undefined" ? window : globalThis);
11915
12103
  }).call(globalThis, void 0, void 0, void 0);
11916
- (function runClassicContentModule35(module, exports, require2) {
12104
+ (function runClassicContentModule36(module, exports, require2) {
11917
12105
  (function initGovernanceRules(root, factory) {
11918
12106
  if (typeof module === "object" && module.exports) {
11919
12107
  let projectFiles = null;
@@ -12130,7 +12318,7 @@ ${block}`;
12130
12318
  };
12131
12319
  });
12132
12320
  }).call(globalThis, void 0, void 0, void 0);
12133
- (function runClassicContentModule36(module, exports, require2) {
12321
+ (function runClassicContentModule37(module, exports, require2) {
12134
12322
  (function initSensitiveScan(root, factory) {
12135
12323
  if (typeof module === "object" && module.exports) {
12136
12324
  module.exports = factory();
@@ -12240,7 +12428,7 @@ ${block}`;
12240
12428
  };
12241
12429
  });
12242
12430
  }).call(globalThis, void 0, void 0, void 0);
12243
- (function runClassicContentModule37(module, exports, require2) {
12431
+ (function runClassicContentModule38(module, exports, require2) {
12244
12432
  (function initAuditRecords(root, factory) {
12245
12433
  if (typeof module === "object" && module.exports) {
12246
12434
  module.exports = factory();
@@ -12766,7 +12954,7 @@ ${block}`;
12766
12954
  };
12767
12955
  });
12768
12956
  }).call(globalThis, void 0, void 0, void 0);
12769
- (function runClassicContentModule38(module, exports, require2) {
12957
+ (function runClassicContentModule39(module, exports, require2) {
12770
12958
  (function initCodexOverleafNativeChannel(root, factory) {
12771
12959
  if (typeof module === "object" && module.exports) {
12772
12960
  module.exports = factory();
@@ -12845,7 +13033,7 @@ ${block}`;
12845
13033
  };
12846
13034
  });
12847
13035
  }).call(globalThis, void 0, void 0, void 0);
12848
- (function runClassicContentModule39(module, exports, require2) {
13036
+ (function runClassicContentModule40(module, exports, require2) {
12849
13037
  (function initCodexOverleafPageBridgeClient(root, factory) {
12850
13038
  const api = factory();
12851
13039
  if (typeof module === "object" && module.exports) module.exports = api;
@@ -12868,6 +13056,7 @@ ${block}`;
12868
13056
  ["src/page/overleafProjectSnapshot.js", "codex-overleaf-project-snapshot-script"],
12869
13057
  ["src/page/pageBridgeCapability.js", "codex-overleaf-page-bridge-capability-script"],
12870
13058
  ["src/page/treeOperations.js", "codex-overleaf-tree-operations-script", true],
13059
+ ["src/page/binaryAssetUploader.js", "codex-overleaf-binary-asset-uploader-script", true],
12871
13060
  ["src/page/snapshotRouter.js", "codex-overleaf-snapshot-router-script"],
12872
13061
  ["src/page/writeGuard.js", "codex-overleaf-write-guard-script", true],
12873
13062
  ["src/page/trackedChangesLifecycle.js", "codex-overleaf-tracked-changes-lifecycle-script", true],
@@ -13047,7 +13236,7 @@ ${block}`;
13047
13236
  });
13048
13237
  });
13049
13238
  }).call(globalThis, void 0, void 0, void 0);
13050
- (function runClassicContentModule40(module, exports, require2) {
13239
+ (function runClassicContentModule41(module, exports, require2) {
13051
13240
  (function initCodexOverleafNativeCompatibilityController(root, factory) {
13052
13241
  const api = factory();
13053
13242
  if (typeof module === "object" && module.exports) module.exports = api;
@@ -13272,8 +13461,8 @@ ${block}`;
13272
13461
  tip.dataset.onboardingTip = "true";
13273
13462
  tip.setAttribute("role", "status");
13274
13463
  tip.textContent = tx(
13275
- "Tip: Start with Ask mode to explore safely. Switch to Suggest to review edits before applying.",
13276
- "\u63D0\u793A\uFF1A\u5148\u7528 Ask \u6A21\u5F0F\u5B89\u5168\u63A2\u7D22\uFF1B\u9700\u8981\u4FEE\u6539\u65F6\u5207\u6362\u5230 Suggest\uFF0C\u5E94\u7528\u524D\u53EF\u5148\u5BA1\u9605\u3002"
13464
+ "Tip: Start with Ask mode to explore safely. Switch to Auto only when you want Codex to edit files.",
13465
+ "\u63D0\u793A\uFF1A\u5148\u7528 Ask \u6A21\u5F0F\u5B89\u5168\u63A2\u7D22\uFF1B\u53EA\u6709\u9700\u8981 Codex \u4FEE\u6539\u6587\u4EF6\u65F6\u624D\u5207\u6362\u5230 Auto\u3002"
13277
13466
  );
13278
13467
  Object.assign(tip.style, {
13279
13468
  position: "absolute",
@@ -13326,7 +13515,7 @@ ${block}`;
13326
13515
  return Object.freeze({ create });
13327
13516
  });
13328
13517
  }).call(globalThis, void 0, void 0, void 0);
13329
- (function runClassicContentModule41(module, exports, require2) {
13518
+ (function runClassicContentModule42(module, exports, require2) {
13330
13519
  (function initCodexOverleafWritebackController(root, factory) {
13331
13520
  if (typeof module === "object" && module.exports) {
13332
13521
  module.exports = factory();
@@ -13343,6 +13532,9 @@ ${block}`;
13343
13532
  type: change.type,
13344
13533
  path: change.path,
13345
13534
  contentBase64: change.contentBase64 || "",
13535
+ assetRef: change.assetRef && typeof change.assetRef === "object" ? { ...change.assetRef } : void 0,
13536
+ sha256: change.sha256 || change.assetRef?.sha256 || "",
13537
+ mimeType: change.mimeType || change.assetRef?.mimeType || "",
13346
13538
  size: Number.isFinite(Number(change.size)) ? Number(change.size) : void 0,
13347
13539
  previousExists: change.previousExists === true,
13348
13540
  previousKind: change.previousKind || "",
@@ -13588,7 +13780,169 @@ ${block}`;
13588
13780
  };
13589
13781
  });
13590
13782
  }).call(globalThis, void 0, void 0, void 0);
13591
- (function runClassicContentModule42(module, exports, require2) {
13783
+ (function runClassicContentModule43(module, exports, require2) {
13784
+ (function initCodexOverleafAssetTransferBroker(root, factory) {
13785
+ const api = factory();
13786
+ if (typeof module === "object" && module.exports) module.exports = api;
13787
+ if (root) root.CodexOverleafAssetTransferBroker = api;
13788
+ })(typeof window !== "undefined" ? window : globalThis, function assetTransferBrokerFactory() {
13789
+ "use strict";
13790
+ const BINARY_TYPES = /* @__PURE__ */ new Set(["binary-create", "overwrite-binary"]);
13791
+ function create(deps = {}) {
13792
+ const { callPageBridge, sendBackgroundNative } = deps;
13793
+ async function applyOperations(input = {}) {
13794
+ const results = [];
13795
+ let textBatch = [];
13796
+ async function flushTextBatch() {
13797
+ if (!textBatch.length) return;
13798
+ results.push(await callPageBridge("applyOperations", {
13799
+ operations: textBatch,
13800
+ baseFiles: input.baseFiles || [],
13801
+ requireReviewing: input.requireReviewing === true,
13802
+ requireEditing: input.requireEditing === true,
13803
+ runProjectId: input.runProjectId || ""
13804
+ }));
13805
+ textBatch = [];
13806
+ }
13807
+ for (const operation of Array.isArray(input.operations) ? input.operations : []) {
13808
+ if (!BINARY_TYPES.has(operation?.type)) {
13809
+ textBatch.push(operation);
13810
+ continue;
13811
+ }
13812
+ await flushTextBatch();
13813
+ results.push(await applyBinaryOperation(operation, input));
13814
+ }
13815
+ await flushTextBatch();
13816
+ return mergeApplyResults(results);
13817
+ }
13818
+ async function applyBinaryOperation(operation, input) {
13819
+ const transferId = `asset_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
13820
+ const assetRef = operation.assetRef || null;
13821
+ const safeOperation = sanitizeOperation(operation);
13822
+ let pageBegun = false;
13823
+ try {
13824
+ const begin = await callPageBridge("binaryUploadBegin", {
13825
+ transferId,
13826
+ path: operation.path,
13827
+ size: Number(operation.size || assetRef?.size || 0),
13828
+ sha256: assetRef?.sha256 || operation.sha256 || "",
13829
+ mimeType: assetRef?.mimeType || operation.mimeType || "application/octet-stream",
13830
+ overwrite: operation.type === "overwrite-binary",
13831
+ runProjectId: input.runProjectId || ""
13832
+ });
13833
+ if (!begin?.ok) throw responseError(begin, "binary_upload_begin_failed");
13834
+ pageBegun = true;
13835
+ if (assetRef?.token) {
13836
+ await streamNativeAsset(assetRef, transferId, input.runProjectId || "");
13837
+ } else if (typeof operation.contentBase64 === "string" && operation.contentBase64) {
13838
+ const append = await callPageBridge("binaryUploadAppend", {
13839
+ transferId,
13840
+ offset: 0,
13841
+ contentBase64: operation.contentBase64,
13842
+ runProjectId: input.runProjectId || ""
13843
+ });
13844
+ if (!append?.ok) throw responseError(append, "binary_upload_chunk_failed");
13845
+ } else {
13846
+ throw codedError("binary_asset_payload_missing", "Binary asset payload is unavailable.");
13847
+ }
13848
+ const committed = await callPageBridge("binaryUploadCommit", {
13849
+ transferId,
13850
+ runProjectId: input.runProjectId || ""
13851
+ });
13852
+ if (!committed?.ok) throw responseError(committed, committed?.code || "binary_upload_failed");
13853
+ return { ok: true, applied: [{ operation: safeOperation, result: committed }], skipped: [] };
13854
+ } catch (error) {
13855
+ if (pageBegun) {
13856
+ await callPageBridge("binaryUploadAbort", { transferId, runProjectId: input.runProjectId || "" }).catch(() => null);
13857
+ }
13858
+ const code = error.code || "binary_upload_failed";
13859
+ return {
13860
+ ok: false,
13861
+ applied: [],
13862
+ skipped: [{
13863
+ operation: safeOperation,
13864
+ path: operation.path,
13865
+ result: {
13866
+ ok: false,
13867
+ code,
13868
+ reason: error.message || "Binary asset upload failed.",
13869
+ changedDocument: false,
13870
+ failure: { code, stage: "write", file: operation.path, changedDocument: false }
13871
+ }
13872
+ }]
13873
+ };
13874
+ } finally {
13875
+ if (assetRef?.token) {
13876
+ await sendBackgroundNative({ method: "asset.release", params: { token: assetRef.token } }).catch(() => null);
13877
+ }
13878
+ }
13879
+ }
13880
+ async function streamNativeAsset(assetRef, transferId, runProjectId) {
13881
+ let offset = 0;
13882
+ while (offset < Number(assetRef.size || 0)) {
13883
+ const response = await sendBackgroundNative({
13884
+ method: "asset.readChunk",
13885
+ params: { token: assetRef.token, offset, length: assetRef.chunkSize || 196608 }
13886
+ });
13887
+ if (!response?.ok) throw responseError(response, response?.error?.code || "asset_chunk_read_failed");
13888
+ const chunk = response.result || {};
13889
+ if (chunk.offset !== offset || typeof chunk.contentBase64 !== "string" || chunk.nextOffset <= offset) {
13890
+ throw codedError("asset_chunk_sequence_invalid", "Native asset chunks arrived out of sequence.");
13891
+ }
13892
+ const appended = await callPageBridge("binaryUploadAppend", {
13893
+ transferId,
13894
+ offset,
13895
+ contentBase64: chunk.contentBase64,
13896
+ runProjectId
13897
+ });
13898
+ if (!appended?.ok) throw responseError(appended, appended?.code || "binary_upload_chunk_failed");
13899
+ offset = chunk.nextOffset;
13900
+ if (chunk.eof) break;
13901
+ }
13902
+ if (offset !== Number(assetRef.size || 0)) {
13903
+ throw codedError("asset_transfer_incomplete", "Native asset transfer ended before the expected size.");
13904
+ }
13905
+ }
13906
+ return { applyOperations };
13907
+ }
13908
+ function mergeApplyResults(results) {
13909
+ const merged = { ok: true, applied: [], skipped: [], trackedChanges: [] };
13910
+ for (const result of results) {
13911
+ merged.applied.push(...Array.isArray(result?.applied) ? result.applied : []);
13912
+ merged.skipped.push(...Array.isArray(result?.skipped) ? result.skipped : []);
13913
+ merged.trackedChanges.push(...Array.isArray(result?.trackedChanges) ? result.trackedChanges : []);
13914
+ if (result?.ok !== true) merged.ok = false;
13915
+ }
13916
+ if (merged.skipped.length) merged.ok = false;
13917
+ return merged;
13918
+ }
13919
+ function sanitizeOperation(operation) {
13920
+ const { contentBase64, assetRef, ...safe } = operation || {};
13921
+ if (assetRef) {
13922
+ safe.asset = {
13923
+ path: assetRef.path || safe.path,
13924
+ size: assetRef.size,
13925
+ sha256: assetRef.sha256,
13926
+ mimeType: assetRef.mimeType
13927
+ };
13928
+ }
13929
+ return safe;
13930
+ }
13931
+ function responseError(response, fallbackCode) {
13932
+ return codedError(
13933
+ response?.code || response?.error?.code || fallbackCode,
13934
+ response?.reason || response?.error?.message || response?.error || "Asset transfer failed."
13935
+ );
13936
+ }
13937
+ function codedError(code, message) {
13938
+ const error = new Error(String(message || code));
13939
+ error.code = code;
13940
+ return error;
13941
+ }
13942
+ return { create, mergeApplyResults };
13943
+ });
13944
+ }).call(globalThis, void 0, void 0, void 0);
13945
+ (function runClassicContentModule44(module, exports, require2) {
13592
13946
  (function initCodexOverleafReviewHunks(root, factory) {
13593
13947
  if (typeof module === "object" && module.exports) {
13594
13948
  module.exports = factory();
@@ -13807,7 +14161,7 @@ ${block}`;
13807
14161
  };
13808
14162
  });
13809
14163
  }).call(globalThis, void 0, void 0, void 0);
13810
- (function runClassicContentModule43(module, exports, require2) {
14164
+ (function runClassicContentModule45(module, exports, require2) {
13811
14165
  (function initCodexOverleafDiffReviewPanel(root, factory) {
13812
14166
  if (typeof module === "object" && module.exports) {
13813
14167
  module.exports = factory(require2("./reviewHunks"));
@@ -14534,7 +14888,7 @@ ${block}`;
14534
14888
  };
14535
14889
  });
14536
14890
  }).call(globalThis, void 0, void 0, void 0);
14537
- (function runClassicContentModule44(module, exports, require2) {
14891
+ (function runClassicContentModule46(module, exports, require2) {
14538
14892
  (function initCodexOverleafContextTray(root, factory) {
14539
14893
  if (typeof module === "object" && module.exports) {
14540
14894
  module.exports = factory(require2("../shared/projectFiles"));
@@ -15282,7 +15636,7 @@ ${block}`;
15282
15636
  };
15283
15637
  });
15284
15638
  }).call(globalThis, void 0, void 0, void 0);
15285
- (function runClassicContentModule45(module, exports, require2) {
15639
+ (function runClassicContentModule47(module, exports, require2) {
15286
15640
  (function initCodexOverleafLocalSkillsPanel(root, factory) {
15287
15641
  if (typeof module === "object" && module.exports) {
15288
15642
  module.exports = factory();
@@ -15513,7 +15867,7 @@ ${block}`;
15513
15867
  };
15514
15868
  });
15515
15869
  }).call(globalThis, void 0, void 0, void 0);
15516
- (function runClassicContentModule46(module, exports, require2) {
15870
+ (function runClassicContentModule48(module, exports, require2) {
15517
15871
  (function initCodexOverleafRunController(root, factory) {
15518
15872
  if (typeof module === "object" && module.exports) {
15519
15873
  module.exports = factory();
@@ -15715,7 +16069,7 @@ ${block}`;
15715
16069
  };
15716
16070
  });
15717
16071
  }).call(globalThis, void 0, void 0, void 0);
15718
- (function runClassicContentModule47(module, exports, require2) {
16072
+ (function runClassicContentModule49(module, exports, require2) {
15719
16073
  (function initCodexOverleafMirrorHealth(root, factory) {
15720
16074
  if (typeof module === "object" && module.exports) {
15721
16075
  module.exports = factory();
@@ -15799,7 +16153,7 @@ ${block}`;
15799
16153
  };
15800
16154
  });
15801
16155
  }).call(globalThis, void 0, void 0, void 0);
15802
- (function runClassicContentModule48(module, exports, require2) {
16156
+ (function runClassicContentModule50(module, exports, require2) {
15803
16157
  (function initCodexOverleafOtWarmMirrorController(root, factory) {
15804
16158
  if (typeof module === "object" && module.exports) {
15805
16159
  module.exports = factory();
@@ -15952,7 +16306,7 @@ ${block}`;
15952
16306
  };
15953
16307
  });
15954
16308
  }).call(globalThis, void 0, void 0, void 0);
15955
- (function runClassicContentModule49(module, exports, require2) {
16309
+ (function runClassicContentModule51(module, exports, require2) {
15956
16310
  (function initComposerAttachments(global) {
15957
16311
  "use strict";
15958
16312
  function createComposerAttachmentController(options2 = {}) {
@@ -16412,7 +16766,7 @@ ${block}`;
16412
16766
  };
16413
16767
  })(window);
16414
16768
  }).call(globalThis, void 0, void 0, void 0);
16415
- (function runClassicContentModule50(module, exports, require2) {
16769
+ (function runClassicContentModule52(module, exports, require2) {
16416
16770
  (function initCodexOverleafPanelRenderer() {
16417
16771
  "use strict";
16418
16772
  const ROOT_CLASS = "codex-overleaf-panel-mounted";
@@ -16732,7 +17086,7 @@ ${block}`;
16732
17086
  };
16733
17087
  })();
16734
17088
  }).call(globalThis, void 0, void 0, void 0);
16735
- (function runClassicContentModule51(module, exports, require2) {
17089
+ (function runClassicContentModule53(module, exports, require2) {
16736
17090
  (function initCodexOverleafSessionPanel() {
16737
17091
  "use strict";
16738
17092
  function create(options2 = {}) {
@@ -16968,7 +17322,7 @@ ${block}`;
16968
17322
  };
16969
17323
  })();
16970
17324
  }).call(globalThis, void 0, void 0, void 0);
16971
- (function runClassicContentModule52(module, exports, require2) {
17325
+ (function runClassicContentModule54(module, exports, require2) {
16972
17326
  (function initCodexOverleafSettingsPanel() {
16973
17327
  "use strict";
16974
17328
  function codexIcon(name) {
@@ -17483,7 +17837,7 @@ ${block}`;
17483
17837
  };
17484
17838
  })();
17485
17839
  }).call(globalThis, void 0, void 0, void 0);
17486
- (function runClassicContentModule53(module, exports, require2) {
17840
+ (function runClassicContentModule55(module, exports, require2) {
17487
17841
  (function initCodexOverleafProviderSettingsDialog() {
17488
17842
  "use strict";
17489
17843
  const CODEX_BLOSSOM_PATH = "M13.798 23.976a5.7 5.7 0 0 1-2.26-.456 6.1 6.1 0 0 1-1.903-1.27 5.7 5.7 0 0 1-1.88.311 5.75 5.75 0 0 1-2.95-.79 6.2 6.2 0 0 1-2.188-2.159q-.81-1.366-.809-3.045 0-.695.19-1.51a6.4 6.4 0 0 1-1.475-2.038A5.95 5.95 0 0 1 0 10.573Q0 9.278.547 8.08q.547-1.2 1.523-2.062a5.5 5.5 0 0 1 2.307-1.223A5.7 5.7 0 0 1 5.472 2.35 6.1 6.1 0 0 1 7.565.623 5.8 5.8 0 0 1 10.206 0q1.19 0 2.26.456a6.1 6.1 0 0 1 1.903 1.27 5.7 5.7 0 0 1 1.88-.311q1.594 0 2.95.79a6 6 0 0 1 2.165 2.159q.832 1.366.832 3.045 0 .695-.19 1.51a6.3 6.3 0 0 1 1.475 2.062q.523 1.15.523 2.422a5.9 5.9 0 0 1-.547 2.493q-.547 1.2-1.546 2.086a5.4 5.4 0 0 1-2.284 1.199 5.56 5.56 0 0 1-1.118 2.445 5.9 5.9 0 0 1-2.07 1.727 5.8 5.8 0 0 1-2.64.623m-5.876-2.997q1.19 0 2.07-.504l4.472-2.589a.53.53 0 0 0 .238-.455v-2.062L8.945 18.7a.96.96 0 0 1-1.047 0l-4.496-2.613a.7.7 0 0 1-.024.168v.287q0 1.224.571 2.254a4.24 4.24 0 0 0 1.642 1.583q1.047.6 2.331.599m.238-3.908a.6.6 0 0 0 .262.072q.118 0 .238-.072l1.784-1.031-5.734-3.357q-.522-.312-.523-.935V6.545a4.3 4.3 0 0 0-1.903 1.63 4.25 4.25 0 0 0-.714 2.398q0 1.176.595 2.254.594 1.08 1.546 1.63zm5.638 5.323q1.26 0 2.284-.576a4.3 4.3 0 0 0 1.618-1.582q.595-1.008.595-2.254v-5.179a.47.47 0 0 0-.238-.431l-1.808-1.055v6.689q0 .624-.524.935l-4.496 2.613a4.3 4.3 0 0 0 2.57.84m.904-8.776v-3.26l-2.688-1.535-2.712 1.535v3.26l2.712 1.535zM7.756 5.97q0-.623.523-.935l4.496-2.613a4.3 4.3 0 0 0-2.569-.84q-1.26 0-2.284.576A4.3 4.3 0 0 0 6.304 3.74q-.57 1.008-.57 2.254v5.155q0 .287.237.455l1.785 1.055zM19.84 17.43a4.16 4.16 0 0 0 1.88-1.63 4.33 4.33 0 0 0 .713-2.397q0-1.176-.595-2.254-.594-1.08-1.546-1.63l-4.449-2.59q-.143-.096-.261-.072a.46.46 0 0 0-.238.072L13.56 7.936l5.758 3.38a.9.9 0 0 1 .38.384q.143.216.143.528zM15.059 5.25q.524-.335 1.047 0l4.52 2.662V7.48q0-1.15-.57-2.181A4.14 4.14 0 0 0 18.46 3.62q-1.023-.623-2.379-.623-1.19 0-2.07.503L9.54 6.09a.53.53 0 0 0-.238.455v2.062z";
@@ -18403,7 +18757,7 @@ ${block}`;
18403
18757
  window.CodexOverleafProviderSettingsDialog = { create, getFooterActionState };
18404
18758
  })();
18405
18759
  }).call(globalThis, void 0, void 0, void 0);
18406
- (function runClassicContentModule54(module, exports, require2) {
18760
+ (function runClassicContentModule56(module, exports, require2) {
18407
18761
  (function initCodexOverleafProjectProviderSelection() {
18408
18762
  "use strict";
18409
18763
  function create(deps = {}) {
@@ -18460,7 +18814,7 @@ ${block}`;
18460
18814
  window.CodexOverleafProjectProviderSelection = { create };
18461
18815
  })();
18462
18816
  }).call(globalThis, void 0, void 0, void 0);
18463
- (function runClassicContentModule55(module, exports, require2) {
18817
+ (function runClassicContentModule57(module, exports, require2) {
18464
18818
  (function initCodexOverleafProviderSettingsCoordinator() {
18465
18819
  "use strict";
18466
18820
  function create(options2 = {}) {
@@ -19053,7 +19407,7 @@ ${block}`;
19053
19407
  window.CodexOverleafProviderSettingsCoordinator = { create };
19054
19408
  })();
19055
19409
  }).call(globalThis, void 0, void 0, void 0);
19056
- (function runClassicContentModule56(module, exports, require2) {
19410
+ (function runClassicContentModule58(module, exports, require2) {
19057
19411
  (function initCodexOverleafSessionPersistence(root, factory) {
19058
19412
  if (typeof module === "object" && module.exports) {
19059
19413
  module.exports = factory(require2("../shared/storageMigration"));
@@ -19147,7 +19501,7 @@ ${block}`;
19147
19501
  };
19148
19502
  });
19149
19503
  }).call(globalThis, void 0, void 0, void 0);
19150
- (function runClassicContentModule57(module, exports, require2) {
19504
+ (function runClassicContentModule59(module, exports, require2) {
19151
19505
  (function(root, factory) {
19152
19506
  var api = factory();
19153
19507
  if (typeof module === "object" && module.exports) module.exports = api;
@@ -19251,7 +19605,7 @@ ${block}`;
19251
19605
  return Object.freeze({ persistPanelState });
19252
19606
  });
19253
19607
  }).call(globalThis, void 0, void 0, void 0);
19254
- (function runClassicContentModule58(module, exports, require2) {
19608
+ (function runClassicContentModule60(module, exports, require2) {
19255
19609
  (function(root, factory) {
19256
19610
  var api = factory();
19257
19611
  if (typeof module === "object" && module.exports) module.exports = api;
@@ -19296,7 +19650,7 @@ ${block}`;
19296
19650
  return Object.freeze({ create });
19297
19651
  });
19298
19652
  }).call(globalThis, void 0, void 0, void 0);
19299
- (function runClassicContentModule59(module, exports, require2) {
19653
+ (function runClassicContentModule61(module, exports, require2) {
19300
19654
  (function(root, factory) {
19301
19655
  if (typeof module === "object" && module.exports) {
19302
19656
  module.exports = factory(
@@ -19391,7 +19745,7 @@ ${block}`;
19391
19745
  });
19392
19746
  });
19393
19747
  }).call(globalThis, void 0, void 0, void 0);
19394
- (function runClassicContentModule60(module, exports, require2) {
19748
+ (function runClassicContentModule62(module, exports, require2) {
19395
19749
  (function initCodexOverleafDiagnosticsPanel() {
19396
19750
  "use strict";
19397
19751
  function create(options2 = {}) {
@@ -19819,7 +20173,7 @@ ${block}`;
19819
20173
  };
19820
20174
  })();
19821
20175
  }).call(globalThis, void 0, void 0, void 0);
19822
- (function runClassicContentModule61(module, exports, require2) {
20176
+ (function runClassicContentModule63(module, exports, require2) {
19823
20177
  (function initCodexOverleafRunQueueScheduler(root, factory) {
19824
20178
  if (typeof module === "object" && module.exports) {
19825
20179
  module.exports = factory(require2("../shared/runInputQueue"));
@@ -20147,7 +20501,7 @@ ${block}`;
20147
20501
  return { create, createCoordinator };
20148
20502
  });
20149
20503
  }).call(globalThis, void 0, void 0, void 0);
20150
- (function runClassicContentModule62(module, exports, require2) {
20504
+ (function runClassicContentModule64(module, exports, require2) {
20151
20505
  (function initCodexOverleafActiveTurnControl(root, factory) {
20152
20506
  if (typeof module === "object" && module.exports) {
20153
20507
  module.exports = factory();
@@ -20316,7 +20670,7 @@ ${block}`;
20316
20670
  return { create };
20317
20671
  });
20318
20672
  }).call(globalThis, void 0, void 0, void 0);
20319
- (function runClassicContentModule63(module, exports, require2) {
20673
+ (function runClassicContentModule65(module, exports, require2) {
20320
20674
  (function initCodexOverleafPendingInputView(root, factory) {
20321
20675
  if (typeof module === "object" && module.exports) {
20322
20676
  module.exports = factory();
@@ -20407,7 +20761,7 @@ ${block}`;
20407
20761
  return { create };
20408
20762
  });
20409
20763
  }).call(globalThis, void 0, void 0, void 0);
20410
- (function runClassicContentModule64(module, exports, require2) {
20764
+ (function runClassicContentModule66(module, exports, require2) {
20411
20765
  (function initCodexOverleafComposerPanel() {
20412
20766
  "use strict";
20413
20767
  function create(options2 = {}) {
@@ -20437,12 +20791,10 @@ ${block}`;
20437
20791
  <span class="codex-mode-label" data-i18n="mode">Mode</span>
20438
20792
  <div class="codex-mode-switch" role="group" aria-label="Write mode">
20439
20793
  <button type="button" data-mode-choice="ask" aria-pressed="false" title="Read and analyze only. Do not write to Overleaf.">Ask</button>
20440
- <button type="button" data-mode-choice="confirm" aria-pressed="false" title="Show a change plan first, then write after approval.">Suggest</button>
20441
20794
  <button type="button" data-mode-choice="auto" aria-pressed="false" title="Write directly after authorization. Deletes still require confirmation.">Auto</button>
20442
20795
  </div>
20443
20796
  <select data-mode aria-label="Mode" hidden>
20444
20797
  <option value="ask">Ask</option>
20445
- <option value="confirm">Suggest</option>
20446
20798
  <option value="auto">Auto</option>
20447
20799
  </select>
20448
20800
  </div>
@@ -20668,7 +21020,7 @@ ${block}`;
20668
21020
  };
20669
21021
  })();
20670
21022
  }).call(globalThis, void 0, void 0, void 0);
20671
- (function runClassicContentModule65(module, exports, require2) {
21023
+ (function runClassicContentModule67(module, exports, require2) {
20672
21024
  (function initCodexOverleafTheme(root, factory) {
20673
21025
  if (typeof module === "object" && module.exports) {
20674
21026
  module.exports = factory();
@@ -20736,7 +21088,7 @@ ${block}`;
20736
21088
  };
20737
21089
  });
20738
21090
  }).call(globalThis, void 0, void 0, void 0);
20739
- (function runClassicContentModule66(module, exports, require2) {
21091
+ (function runClassicContentModule68(module, exports, require2) {
20740
21092
  !(function(e, t) {
20741
21093
  "object" == typeof exports && "object" == typeof module ? module.exports = t() : "function" == typeof define && define.amd ? define([], t) : "object" == typeof exports ? exports.katex = t() : e.katex = t();
20742
21094
  })("undefined" != typeof self ? self : this, function() {
@@ -24156,7 +24508,7 @@ ${block}`;
24156
24508
  })();
24157
24509
  });
24158
24510
  }).call(globalThis, void 0, void 0, void 0);
24159
- (function runClassicContentModule67(module, exports, require2) {
24511
+ (function runClassicContentModule69(module, exports, require2) {
24160
24512
  !(function(t, e) {
24161
24513
  "object" == typeof exports && "undefined" != typeof module ? module.exports = e() : "function" == typeof define && define.amd ? define([], e) : (t = "undefined" != typeof globalThis ? globalThis : t || self).markdownit = e();
24162
24514
  })(this, function() {
@@ -26228,7 +26580,7 @@ ${block}`;
26228
26580
  }, Ke;
26229
26581
  });
26230
26582
  }).call(globalThis, void 0, void 0, void 0);
26231
- (function runClassicContentModule68(module, exports, require2) {
26583
+ (function runClassicContentModule70(module, exports, require2) {
26232
26584
  (function initCodexOverleafMathText(root) {
26233
26585
  "use strict";
26234
26586
  const DELIMITERS = Object.freeze([
@@ -26239,6 +26591,19 @@ ${block}`;
26239
26591
  ]);
26240
26592
  const LONG_INLINE_MATH_CHARS = 120;
26241
26593
  const COMPLEX_INLINE_MATH_CHARS = 80;
26594
+ const MAX_PROJECT_MACRO_SOURCES = 12;
26595
+ const MAX_PROJECT_MACRO_SOURCE_CHARS = 256 * 1024;
26596
+ const MAX_PROJECT_MACROS = 64;
26597
+ const MAX_MACRO_EXPANSION_CHARS = 512;
26598
+ const DEFAULT_MATH_MACROS = Object.freeze({
26599
+ "\\E": "\\mathbb{E}",
26600
+ "\\Var": "\\operatorname{Var}",
26601
+ "\\Cov": "\\operatorname{Cov}",
26602
+ "\\R": "\\mathbb{R}",
26603
+ "\\N": "\\mathbb{N}",
26604
+ "\\Z": "\\mathbb{Z}"
26605
+ });
26606
+ const UNSAFE_MACRO_PATTERN = /\\(?:href|url|includegraphics|input|include|write|openout|read|html\w*|class|style|data|def|gdef|edef|xdef|newcommand|renewcommand|providecommand|DeclareMathOperator)\b/i;
26242
26607
  function parseMathSegments(value) {
26243
26608
  const source = String(value || "");
26244
26609
  if (!source) {
@@ -26300,9 +26665,10 @@ ${block}`;
26300
26665
  searchFrom = start + delimiter.open.length;
26301
26666
  continue;
26302
26667
  }
26303
- const value = source.slice(start + delimiter.open.length, closeStart);
26668
+ const rawValue = source.slice(start + delimiter.open.length, closeStart);
26669
+ const value = rawValue.trim();
26304
26670
  const end = closeStart + delimiter.close.length;
26305
- if (!isValidMathValue(value, delimiter) || overlapsCodeRange(start, end, codeRanges)) {
26671
+ if (!isValidMathValue(rawValue, delimiter) || overlapsCodeRange(start, end, codeRanges)) {
26306
26672
  searchFrom = start + delimiter.open.length;
26307
26673
  continue;
26308
26674
  }
@@ -26319,7 +26685,7 @@ ${block}`;
26319
26685
  }
26320
26686
  const previous = source[index - 1] || "";
26321
26687
  const next = source[index + 1] || "";
26322
- return previous !== "$" && next !== "$" && next !== "" && !/\s/.test(next);
26688
+ return previous !== "$" && next !== "$" && next !== "";
26323
26689
  }
26324
26690
  function findClosingDelimiter(source, fromIndex, delimiter, codeRanges) {
26325
26691
  let searchFrom = fromIndex;
@@ -26330,7 +26696,7 @@ ${block}`;
26330
26696
  }
26331
26697
  const previous = source[index - 1] || "";
26332
26698
  const next = source[index + delimiter.close.length] || "";
26333
- const invalidSingleDollar = delimiter.singleDollar && (previous === "$" || next === "$" || /\s/.test(previous));
26699
+ const invalidSingleDollar = delimiter.singleDollar && (previous === "$" || next === "$");
26334
26700
  if (!isEscaped(source, index) && !isInsideRange(index, codeRanges) && !invalidSingleDollar) {
26335
26701
  return index;
26336
26702
  }
@@ -26340,10 +26706,21 @@ ${block}`;
26340
26706
  }
26341
26707
  function isValidMathValue(value, delimiter) {
26342
26708
  const source = String(value || "");
26343
- if (!source.trim()) {
26709
+ const trimmed = source.trim();
26710
+ if (!trimmed) {
26711
+ return false;
26712
+ }
26713
+ if (!delimiter.display && /[\r\n]/.test(source)) {
26344
26714
  return false;
26345
26715
  }
26346
- return delimiter.display || !/[\r\n]/.test(source);
26716
+ if (!delimiter.singleDollar || !/^\s/.test(source) && !/\s$/.test(source)) {
26717
+ return true;
26718
+ }
26719
+ return looksLikeWhitespaceWrappedMath(trimmed);
26720
+ }
26721
+ function looksLikeWhitespaceWrappedMath(value) {
26722
+ const source = String(value || "").trim();
26723
+ return /\\[A-Za-z]+/.test(source) || /[_^=<>+\-*/()[\]{}|]/.test(source) || /^[A-Za-z](?:_[A-Za-z0-9{}]+|\^[A-Za-z0-9{}]+)?$/.test(source);
26347
26724
  }
26348
26725
  function collectInlineCodeRanges(source) {
26349
26726
  const ranges = [];
@@ -26394,7 +26771,8 @@ ${block}`;
26394
26771
  }
26395
26772
  nodes.push(createMathNode(segment, {
26396
26773
  document: documentRef,
26397
- katex: options2.katex || root.katex
26774
+ katex: options2.katex || root.katex,
26775
+ macros: options2.macros || buildMathMacros(options2.projectSources)
26398
26776
  }));
26399
26777
  }
26400
26778
  return nodes;
@@ -26420,6 +26798,7 @@ ${block}`;
26420
26798
  strict: "warn",
26421
26799
  maxExpand: 200,
26422
26800
  maxSize: 20,
26801
+ macros: options2.macros || buildMathMacros(),
26423
26802
  output: "htmlAndMathml"
26424
26803
  });
26425
26804
  node.dataset.mathRendered = "true";
@@ -26427,7 +26806,7 @@ ${block}`;
26427
26806
  } catch (_error) {
26428
26807
  node.classList.add("run-math--fallback");
26429
26808
  node.dataset.mathRendered = "false";
26430
- node.textContent = segment.raw;
26809
+ node.textContent = source;
26431
26810
  return node;
26432
26811
  }
26433
26812
  }
@@ -26444,6 +26823,106 @@ ${block}`;
26444
26823
  }
26445
26824
  return /(?:=|\\(?:le|ge|approx|sim|to|Rightarrow|Longrightarrow)\b|\\begin\{(?:aligned|gathered|split|array)\}|\\\\)/.test(source);
26446
26825
  }
26826
+ function parseStandaloneMath(value) {
26827
+ const source = String(value || "").trim();
26828
+ if (!source) {
26829
+ return null;
26830
+ }
26831
+ const segments = parseMathSegments(source);
26832
+ if (segments.length !== 1 || segments[0].type !== "math" || segments[0].raw !== source) {
26833
+ return null;
26834
+ }
26835
+ return segments[0];
26836
+ }
26837
+ function buildMathMacros(projectSources = []) {
26838
+ const macros = { ...DEFAULT_MATH_MACROS };
26839
+ let remainingChars = MAX_PROJECT_MACRO_SOURCE_CHARS;
26840
+ let projectMacroCount = 0;
26841
+ for (const sourceRecord of Array.isArray(projectSources) ? projectSources.slice(0, MAX_PROJECT_MACRO_SOURCES) : []) {
26842
+ if (projectMacroCount >= MAX_PROJECT_MACROS || remainingChars <= 0) {
26843
+ break;
26844
+ }
26845
+ const path = String(sourceRecord?.path || "");
26846
+ if (!/\.(?:tex|sty|cls|ltx)$/i.test(path)) {
26847
+ continue;
26848
+ }
26849
+ const source = stripLatexComments(
26850
+ String(sourceRecord?.content || "").slice(0, remainingChars)
26851
+ );
26852
+ remainingChars -= source.length;
26853
+ const pattern = /\\(newcommand|renewcommand|providecommand|DeclareMathOperator)(\*)?/g;
26854
+ let match;
26855
+ while ((match = pattern.exec(source)) !== null && projectMacroCount < MAX_PROJECT_MACROS) {
26856
+ let cursor = skipWhitespace(source, pattern.lastIndex);
26857
+ const nameGroup = readBracedGroup(source, cursor);
26858
+ if (!nameGroup) {
26859
+ continue;
26860
+ }
26861
+ const macroName = nameGroup.value.trim();
26862
+ cursor = skipWhitespace(source, nameGroup.end);
26863
+ if (source[cursor] === "[") {
26864
+ continue;
26865
+ }
26866
+ const expansionGroup = readBracedGroup(source, cursor);
26867
+ if (!expansionGroup) {
26868
+ continue;
26869
+ }
26870
+ let expansion = expansionGroup.value.trim();
26871
+ if (match[1] === "DeclareMathOperator") {
26872
+ expansion = `\\operatorname${match[2] ? "*" : ""}{${expansion}}`;
26873
+ }
26874
+ if (!isSafeMacroDefinition(macroName, expansion)) {
26875
+ continue;
26876
+ }
26877
+ macros[macroName] = expansion;
26878
+ projectMacroCount++;
26879
+ pattern.lastIndex = expansionGroup.end;
26880
+ }
26881
+ }
26882
+ return macros;
26883
+ }
26884
+ function readBracedGroup(source, start) {
26885
+ if (source[start] !== "{") {
26886
+ return null;
26887
+ }
26888
+ let depth = 0;
26889
+ for (let index = start; index < source.length; index++) {
26890
+ if (source[index] === "{" && !isEscaped(source, index)) {
26891
+ depth++;
26892
+ } else if (source[index] === "}" && !isEscaped(source, index)) {
26893
+ depth--;
26894
+ if (depth === 0) {
26895
+ return {
26896
+ value: source.slice(start + 1, index),
26897
+ end: index + 1
26898
+ };
26899
+ }
26900
+ }
26901
+ }
26902
+ return null;
26903
+ }
26904
+ function skipWhitespace(source, start) {
26905
+ let index = start;
26906
+ while (index < source.length && /\s/.test(source[index])) {
26907
+ index++;
26908
+ }
26909
+ return index;
26910
+ }
26911
+ function stripLatexComments(source) {
26912
+ return String(source || "").split(/\r?\n/).map((line) => {
26913
+ for (let index = 0; index < line.length; index++) {
26914
+ if (line[index] === "%" && !isEscaped(line, index)) {
26915
+ return line.slice(0, index);
26916
+ }
26917
+ }
26918
+ return line;
26919
+ }).join("\n");
26920
+ }
26921
+ function isSafeMacroDefinition(name, expansion) {
26922
+ const macroName = String(name || "");
26923
+ const body = String(expansion || "");
26924
+ return /^\\[A-Za-z@]+$/.test(macroName) && body.length > 0 && body.length <= MAX_MACRO_EXPANSION_CHARS && !body.includes("#") && !body.includes(macroName) && !UNSAFE_MACRO_PATTERN.test(macroName) && !UNSAFE_MACRO_PATTERN.test(body);
26925
+ }
26447
26926
  function toNodeArray(value) {
26448
26927
  if (Array.isArray(value)) {
26449
26928
  return value;
@@ -26472,11 +26951,13 @@ ${block}`;
26472
26951
  };
26473
26952
  }
26474
26953
  const api = {
26954
+ buildMathMacros,
26475
26955
  buildMathNodes,
26476
26956
  createMathNode,
26477
26957
  matchMathAt,
26478
26958
  normalizeMathForRendering,
26479
- parseMathSegments
26959
+ parseMathSegments,
26960
+ parseStandaloneMath
26480
26961
  };
26481
26962
  root.CodexOverleafMathText = api;
26482
26963
  if (typeof module !== "undefined" && module.exports) {
@@ -26484,7 +26965,7 @@ ${block}`;
26484
26965
  }
26485
26966
  })(typeof window !== "undefined" ? window : globalThis);
26486
26967
  }).call(globalThis, void 0, void 0, void 0);
26487
- (function runClassicContentModule69(module, exports, require2) {
26968
+ (function runClassicContentModule71(module, exports, require2) {
26488
26969
  (function initCodexOverleafMarkdownDomRenderer(root, factory) {
26489
26970
  const api = factory();
26490
26971
  if (typeof module === "object" && module.exports) {
@@ -26912,7 +27393,7 @@ ${block}`;
26912
27393
  };
26913
27394
  });
26914
27395
  }).call(globalThis, void 0, void 0, void 0);
26915
- (function runClassicContentModule70(module, exports, require2) {
27396
+ (function runClassicContentModule72(module, exports, require2) {
26916
27397
  (function initCodexOverleafMarkdownText() {
26917
27398
  "use strict";
26918
27399
  function create(deps = {}) {
@@ -26923,11 +27404,15 @@ ${block}`;
26923
27404
  callPageBridge,
26924
27405
  getCurrentProjectId,
26925
27406
  getCurrentProjectReferenceFiles,
27407
+ getCurrentProjectMathSources,
26926
27408
  showPluginToast
26927
27409
  } = deps;
26928
27410
  function renderMarkdownInlineText(target, value) {
26929
27411
  target.replaceChildren(...buildMarkdownInlineNodes(value));
26930
27412
  }
27413
+ function getMathMacros() {
27414
+ return MathText?.buildMathMacros?.(getCurrentProjectMathSources?.() || []) || {};
27415
+ }
26931
27416
  function sanitizeAssistantVisibleText(value) {
26932
27417
  if (typeof value !== "string" || !value) {
26933
27418
  return "";
@@ -26976,6 +27461,7 @@ ${block}`;
26976
27461
  return mathText.buildMathNodes(source, {
26977
27462
  document,
26978
27463
  katex: window.katex,
27464
+ macros: getMathMacros(),
26979
27465
  renderText: buildMarkdownInlineNodesWithoutMath
26980
27466
  });
26981
27467
  }
@@ -27008,6 +27494,11 @@ ${block}`;
27008
27494
  function buildInlineCodeNodes(value) {
27009
27495
  const source = String(value || "");
27010
27496
  const trimmed = source.trim();
27497
+ const standaloneMath = MathText?.parseStandaloneMath?.(trimmed);
27498
+ if (standaloneMath && MathText?.createMathNode) return [MathText.createMathNode(
27499
+ standaloneMath,
27500
+ { document, katex: window.katex, macros: getMathMacros() }
27501
+ )];
27011
27502
  const refs = trimmed ? parseRuntimeLineReferences(trimmed, "plain-text-token") : [];
27012
27503
  const ref = refs.length === 1 && refs[0]?.rawText === trimmed ? refs[0] : null;
27013
27504
  if (ref && !isRuntimeLocalPathLike(ref.rawPath)) {
@@ -27348,13 +27839,17 @@ ${block}`;
27348
27839
  `[${safeLabel.replace(/]/g, "\\]")}](${target2.replace(/\)/g, "\\)")})`
27349
27840
  );
27350
27841
  },
27351
- renderCodeNodes: (text) => buildMarkdownInlineNodes(`\`${String(text || "").replace(/`/g, "\\`")}\``),
27842
+ renderCodeNodes: (text) => buildInlineCodeNodes(text),
27352
27843
  sanitizeText: sanitizeAssistantVisibleText,
27353
- createMathNode: (segment) => runtimeRoot.CodexOverleafMathText.createMathNode(segment, {
27354
- document,
27355
- katex: runtimeRoot.katex,
27356
- renderText: (text) => buildMarkdownInlineNodes(text)
27357
- }),
27844
+ createMathNode: (segment) => runtimeRoot.CodexOverleafMathText.createMathNode(
27845
+ segment,
27846
+ {
27847
+ document,
27848
+ katex: runtimeRoot.katex,
27849
+ macros: getMathMacros(),
27850
+ renderText: (text) => buildMarkdownInlineNodes(text)
27851
+ }
27852
+ ),
27358
27853
  recordDiagnostic: recordRenderingDiagnostic
27359
27854
  });
27360
27855
  return;
@@ -27525,7 +28020,7 @@ ${block}`;
27525
28020
  window.CodexOverleafMarkdownText = { create };
27526
28021
  })();
27527
28022
  }).call(globalThis, void 0, void 0, void 0);
27528
- (function runClassicContentModule71(module, exports, require2) {
28023
+ (function runClassicContentModule73(module, exports, require2) {
27529
28024
  (function initCodexOverleafDiagnosticsController() {
27530
28025
  "use strict";
27531
28026
  function create(deps = {}) {
@@ -28094,7 +28589,7 @@ ${block}`;
28094
28589
  window.CodexOverleafDiagnosticsController = { create };
28095
28590
  })();
28096
28591
  }).call(globalThis, void 0, void 0, void 0);
28097
- (function runClassicContentModule72(module, exports, require2) {
28592
+ (function runClassicContentModule74(module, exports, require2) {
28098
28593
  (function initCodexOverleafRunGuidanceView() {
28099
28594
  "use strict";
28100
28595
  const LEGACY_GUIDANCE_TITLES = /* @__PURE__ */ new Set([
@@ -28134,7 +28629,7 @@ ${block}`;
28134
28629
  };
28135
28630
  })();
28136
28631
  }).call(globalThis, void 0, void 0, void 0);
28137
- (function runClassicContentModule73(module, exports, require2) {
28632
+ (function runClassicContentModule75(module, exports, require2) {
28138
28633
  (function initCodexOverleafRunGuidanceController() {
28139
28634
  "use strict";
28140
28635
  function create(deps = {}) {
@@ -28197,12 +28692,118 @@ ${block}`;
28197
28692
  window.CodexOverleafRunGuidanceController = { create };
28198
28693
  })();
28199
28694
  }).call(globalThis, void 0, void 0, void 0);
28200
- (function runClassicContentModule74(module, exports, require2) {
28695
+ (function runClassicContentModule76(module, exports, require2) {
28696
+ (function initCodexOverleafRunResultActions(root, factory) {
28697
+ const api = factory();
28698
+ if (typeof module === "object" && module.exports) module.exports = api;
28699
+ if (root) root.CodexOverleafRunResultActions = api;
28700
+ })(typeof window !== "undefined" ? window : globalThis, function runResultActionsFactory() {
28701
+ "use strict";
28702
+ function create(deps = {}) {
28703
+ const {
28704
+ tr,
28705
+ getLocale,
28706
+ forkRunFromNode,
28707
+ document: documentRef = globalThis.document,
28708
+ navigator: navigatorRef = globalThis.navigator
28709
+ } = deps;
28710
+ function configureResultActions(root, run) {
28711
+ const actions = root.querySelector(".run-result-actions");
28712
+ const reports = root.querySelectorAll(".run-completion-report");
28713
+ const report = reports[reports.length - 1];
28714
+ if (!actions || !report) return;
28715
+ report.append(actions);
28716
+ actions.hidden = false;
28717
+ configureCopyButton(root);
28718
+ configureForkButton(root, run);
28719
+ configureCompletedTime(actions, run);
28720
+ }
28721
+ function configureForkButton(root, run) {
28722
+ const existing = root.querySelector("[data-run-fork]");
28723
+ const button = existing.cloneNode(true);
28724
+ existing.replaceWith(button);
28725
+ const available = run.forkSnapshot !== true && run.status !== "running" && Boolean(run.codexTurnId) && typeof forkRunFromNode === "function";
28726
+ button.hidden = false;
28727
+ button.disabled = !available;
28728
+ button.title = tr(available ? "forkRunTitle" : "forkRunUnavailable");
28729
+ button.setAttribute("aria-label", button.title);
28730
+ button.innerHTML = '<svg viewBox="0 0 20 20" aria-hidden="true"><path d="M3 10h3.5c3.5 0 4.2-4 7.5-4h2m-2.5-2.5L16 6l-2.5 2.5M6.5 10c3.5 0 4.2 4 7.5 4h2m-2.5-2.5L16 14l-2.5 2.5"/></svg>';
28731
+ if (!available) return;
28732
+ button.addEventListener("click", async (event) => {
28733
+ event.stopPropagation();
28734
+ button.disabled = true;
28735
+ button.classList.add("is-running");
28736
+ try {
28737
+ await forkRunFromNode(run.id);
28738
+ } catch (_error) {
28739
+ button.disabled = false;
28740
+ button.classList.remove("is-running");
28741
+ }
28742
+ });
28743
+ }
28744
+ function configureCompletedTime(actions, run) {
28745
+ const target = actions.querySelector("[data-run-completed-time]");
28746
+ const finishedAt = String(run.finishedAt || "").trim();
28747
+ const date = finishedAt ? new Date(finishedAt) : null;
28748
+ if (!target || !date || !Number.isFinite(date.getTime())) return;
28749
+ target.hidden = false;
28750
+ target.textContent = new Intl.DateTimeFormat(getLocale(), {
28751
+ hour: "2-digit",
28752
+ minute: "2-digit"
28753
+ }).format(date);
28754
+ target.title = date.toLocaleString(getLocale());
28755
+ }
28756
+ function configureCopyButton(root) {
28757
+ const existing = root.querySelector("[data-run-copy]");
28758
+ const button = existing.cloneNode(true);
28759
+ existing.replaceWith(button);
28760
+ const finalAnswer = root.querySelector(".run-completion-report .run-final-answer");
28761
+ const copyText = String(finalAnswer?.innerText || finalAnswer?.textContent || "").trim();
28762
+ button.hidden = false;
28763
+ button.disabled = !copyText;
28764
+ button.title = tr("copyConclusionTitle");
28765
+ button.setAttribute("aria-label", button.title);
28766
+ button.innerHTML = '<svg viewBox="0 0 20 20" aria-hidden="true"><rect x="6.5" y="6.5" width="9" height="9" rx="2"/><path d="M13.5 6.5V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v6.5a2 2 0 0 0 2 2h1.5"/></svg>';
28767
+ if (!copyText) return;
28768
+ button.addEventListener("click", async (event) => {
28769
+ event.stopPropagation();
28770
+ try {
28771
+ await writeClipboardText(copyText);
28772
+ button.title = tr("copyConclusionDone");
28773
+ } catch (_error) {
28774
+ button.title = tr("copyConclusionFailed");
28775
+ }
28776
+ button.setAttribute("aria-label", button.title);
28777
+ });
28778
+ }
28779
+ async function writeClipboardText(text) {
28780
+ if (navigatorRef?.clipboard?.writeText) {
28781
+ await navigatorRef.clipboard.writeText(text);
28782
+ return;
28783
+ }
28784
+ const textarea = documentRef.createElement("textarea");
28785
+ textarea.value = text;
28786
+ textarea.setAttribute("readonly", "");
28787
+ textarea.style.position = "fixed";
28788
+ textarea.style.opacity = "0";
28789
+ documentRef.body.append(textarea);
28790
+ textarea.select();
28791
+ const copied = documentRef.execCommand("copy");
28792
+ textarea.remove();
28793
+ if (!copied) throw new Error("clipboard_copy_failed");
28794
+ }
28795
+ return Object.freeze({ configureResultActions });
28796
+ }
28797
+ return Object.freeze({ create });
28798
+ });
28799
+ }).call(globalThis, void 0, void 0, void 0);
28800
+ (function runClassicContentModule77(module, exports, require2) {
28201
28801
  (function initCodexOverleafRunTimelineView() {
28202
28802
  "use strict";
28203
28803
  function create(deps = {}) {
28204
28804
  const {
28205
28805
  RunGuidanceView,
28806
+ RunResultActions,
28206
28807
  tr,
28207
28808
  tx,
28208
28809
  getLocale,
@@ -28413,6 +29014,9 @@ ${block}`;
28413
29014
  if (status === "failed") {
28414
29015
  return tr("processedFailed", { elapsed });
28415
29016
  }
29017
+ if (status === "rejected" || status === "cancelled") {
29018
+ return tr("processedCancelled", { elapsed });
29019
+ }
28416
29020
  if (status === "running") {
28417
29021
  return tr("processing", { elapsed });
28418
29022
  }
@@ -28481,6 +29085,11 @@ ${block}`;
28481
29085
  </summary>
28482
29086
  </details>
28483
29087
  <div class="run-activity-list" data-run-events></div>
29088
+ <div class="run-result-actions" hidden>
29089
+ <button type="button" class="run-copy-action" data-run-copy hidden></button>
29090
+ <button type="button" class="run-fork-action" data-run-fork hidden></button>
29091
+ <span class="run-completed-time" data-run-completed-time hidden></span>
29092
+ </div>
28484
29093
  <div class="run-report" data-run-report aria-live="polite" hidden></div>
28485
29094
  </div>
28486
29095
  `;
@@ -28529,6 +29138,7 @@ ${block}`;
28529
29138
  events.append(renderRunEvent(event));
28530
29139
  }
28531
29140
  }
29141
+ RunResultActions.configureResultActions(root, run);
28532
29142
  configureAcceptButton(root, run);
28533
29143
  configureUndoButton(root, run);
28534
29144
  return root;
@@ -28543,6 +29153,9 @@ ${block}`;
28543
29153
  if (run.startedAt && run.finishedAt) {
28544
29154
  return formatProcessedSummary(run.status || "completed", new Date(run.finishedAt).getTime() - new Date(run.startedAt).getTime());
28545
29155
  }
29156
+ if (run.status === "rejected" || run.status === "cancelled") {
29157
+ return tx("Cancelled", "\u5DF2\u53D6\u6D88");
29158
+ }
28546
29159
  return run.status === "failed" ? tx("Failed", "\u5904\u7406\u5931\u8D25") : tx("Done", "\u5DF2\u5904\u7406");
28547
29160
  }
28548
29161
  function renderRunEvent(event) {
@@ -28963,6 +29576,10 @@ ${conclusion}` : `${label} ${conclusion}`;
28963
29576
  const existing = root.querySelector("[data-run-undo]");
28964
29577
  const button = existing.cloneNode(true);
28965
29578
  existing.replaceWith(button);
29579
+ if (run.forkSnapshot === true) {
29580
+ button.hidden = true;
29581
+ return;
29582
+ }
28966
29583
  if (isTrackedChangeLifecycleRun(run)) {
28967
29584
  configureLifecycleUndoButton(button, run);
28968
29585
  return;
@@ -29031,6 +29648,10 @@ ${conclusion}` : `${label} ${conclusion}`;
29031
29648
  const existing = root.querySelector("[data-run-accept]");
29032
29649
  const button = existing.cloneNode(true);
29033
29650
  existing.replaceWith(button);
29651
+ if (run.forkSnapshot === true) {
29652
+ button.hidden = true;
29653
+ return;
29654
+ }
29034
29655
  if (!isTrackedChangeLifecycleRun(run)) {
29035
29656
  button.hidden = true;
29036
29657
  return;
@@ -29145,7 +29766,7 @@ ${conclusion}` : `${label} ${conclusion}`;
29145
29766
  window.CodexOverleafRunTimelineView = { create };
29146
29767
  })();
29147
29768
  }).call(globalThis, void 0, void 0, void 0);
29148
- (function runClassicContentModule75(module, exports, require2) {
29769
+ (function runClassicContentModule78(module, exports, require2) {
29149
29770
  (function initCodexOverleafProjectSettingsCoordinator() {
29150
29771
  "use strict";
29151
29772
  function create(deps = {}) {
@@ -29472,7 +30093,7 @@ ${conclusion}` : `${label} ${conclusion}`;
29472
30093
  window.CodexOverleafProjectSettingsCoordinator = { create };
29473
30094
  })();
29474
30095
  }).call(globalThis, void 0, void 0, void 0);
29475
- (function runClassicContentModule76(module, exports, require2) {
30096
+ (function runClassicContentModule79(module, exports, require2) {
29476
30097
  (function initCodexOverleafSessionMenuView() {
29477
30098
  "use strict";
29478
30099
  function create(deps = {}) {
@@ -29677,7 +30298,7 @@ ${conclusion}` : `${label} ${conclusion}`;
29677
30298
  window.CodexOverleafSessionMenuView = { create };
29678
30299
  })();
29679
30300
  }).call(globalThis, void 0, void 0, void 0);
29680
- (function runClassicContentModule77(module, exports, require2) {
30301
+ (function runClassicContentModule80(module, exports, require2) {
29681
30302
  (function initCodexOverleafSessionManager() {
29682
30303
  "use strict";
29683
30304
  function create(deps = {}) {
@@ -29936,7 +30557,136 @@ ${conclusion}` : `${label} ${conclusion}`;
29936
30557
  window.CodexOverleafSessionManager = { create };
29937
30558
  })();
29938
30559
  }).call(globalThis, void 0, void 0, void 0);
29939
- (function runClassicContentModule78(module, exports, require2) {
30560
+ (function runClassicContentModule81(module, exports, require2) {
30561
+ (function initCodexOverleafSessionForkController(root, factory) {
30562
+ const api = factory();
30563
+ if (typeof module === "object" && module.exports) module.exports = api;
30564
+ if (root) root.CodexOverleafSessionForkController = api;
30565
+ })(typeof window !== "undefined" ? window : globalThis, function sessionForkControllerFactory() {
30566
+ "use strict";
30567
+ function create(deps = {}) {
30568
+ const {
30569
+ SessionState,
30570
+ getState,
30571
+ setState,
30572
+ sendBackgroundNative,
30573
+ saveState,
30574
+ applyStateToPanel,
30575
+ showPluginToast,
30576
+ tr
30577
+ } = deps;
30578
+ async function forkRunFromNode(runId) {
30579
+ const previousState = getState();
30580
+ const source = findSource(previousState, runId);
30581
+ if (!source) return failFork("session_fork_source_missing", tr("forkRunUnavailable"));
30582
+ const { session, run, runIndex } = source;
30583
+ if (run.status === "running" || !session.codexThreadId || !run.codexTurnId) {
30584
+ return failFork("session_fork_unavailable", tr("forkRunUnavailable"));
30585
+ }
30586
+ const response = await sendBackgroundNative({
30587
+ method: "codex.thread.fork",
30588
+ params: {
30589
+ threadId: session.codexThreadId,
30590
+ lastTurnId: run.codexTurnId,
30591
+ speedTier: session.speedTier,
30592
+ loadCodexLocalSkills: previousState.loadCodexLocalSkills !== false,
30593
+ loadCodexOverleafSkills: previousState.loadCodexOverleafSkills !== false
30594
+ }
30595
+ });
30596
+ if (!response?.ok || !response.result?.threadId) {
30597
+ return failFork(response?.error?.code || "session_fork_failed", response?.error?.message || tr("forkRunFailed"));
30598
+ }
30599
+ const copiedRuns = session.runs.slice(0, runIndex + 1).map(copyRunSnapshot);
30600
+ const titleBase = String(session.title || copiedRuns[0]?.task || tr("newSessionFallback")).trim();
30601
+ const forkTitle = buildUniqueForkTitle(previousState.sessions, titleBase);
30602
+ const forked = SessionState.createSession({
30603
+ title: forkTitle,
30604
+ titleSource: "manual",
30605
+ runs: copiedRuns,
30606
+ task: "",
30607
+ mode: session.mode,
30608
+ providerId: session.providerId,
30609
+ model: session.model,
30610
+ reasoningEffort: session.reasoningEffort,
30611
+ speedTier: session.speedTier,
30612
+ requireReviewing: session.requireReviewing,
30613
+ focusFiles: session.focusFiles,
30614
+ projectReferenceFiles: session.projectReferenceFiles,
30615
+ codexThreadId: response.result.threadId,
30616
+ pendingInputs: [],
30617
+ forkedFromSessionId: session.id,
30618
+ forkedFromRunId: run.id
30619
+ });
30620
+ setState(SessionState.normalizePanelState({
30621
+ ...previousState,
30622
+ sessions: [...previousState.sessions || [], forked],
30623
+ activeSessionId: forked.id
30624
+ }));
30625
+ try {
30626
+ await saveState();
30627
+ } catch (error) {
30628
+ setState(previousState);
30629
+ await sendBackgroundNative({
30630
+ method: "codex.history.clearPlugin",
30631
+ params: { sessionId: forked.id, threadId: response.result.threadId }
30632
+ }).catch(() => null);
30633
+ showPluginToast(error.message || tr("forkRunFailed"), { status: "failed", sticky: true });
30634
+ throw error;
30635
+ }
30636
+ applyStateToPanel();
30637
+ showPluginToast(tr("forkRunDone"), { status: "completed" });
30638
+ return forked;
30639
+ }
30640
+ function failFork(code, message) {
30641
+ showPluginToast(message, { status: "failed", sticky: true });
30642
+ throw codedError(code, message);
30643
+ }
30644
+ return { forkRunFromNode };
30645
+ }
30646
+ function buildUniqueForkTitle(sessions = [], sourceTitle = "") {
30647
+ const fallback = String(sourceTitle || "New Session").trim() || "New Session";
30648
+ const baseTitle = fallback.replace(/\s+\(fork\)$/i, "").replace(/\s+\(\d+\)$/, "").trim() || fallback;
30649
+ const usedTitles = new Set((sessions || []).map((session) => String(session?.title || "").trim()));
30650
+ let index = 1;
30651
+ while (usedTitles.has(`${baseTitle} (${index})`)) index += 1;
30652
+ return `${baseTitle} (${index})`;
30653
+ }
30654
+ function findSource(state, runId) {
30655
+ for (const session of state?.sessions || []) {
30656
+ const runIndex = (session.runs || []).findIndex((run) => run.id === runId);
30657
+ if (runIndex >= 0) return { session, run: session.runs[runIndex], runIndex };
30658
+ }
30659
+ return null;
30660
+ }
30661
+ function copyRunSnapshot(run) {
30662
+ const copy = JSON.parse(JSON.stringify(run || {}));
30663
+ return {
30664
+ ...copy,
30665
+ id: `fork_${String(copy.id || "run")}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 7)}`,
30666
+ forkSnapshot: true,
30667
+ forkSourceRunId: String(copy.id || ""),
30668
+ attachments: [],
30669
+ appliedOperations: [],
30670
+ undoOperations: [],
30671
+ undoBaseFiles: [],
30672
+ undoTrackedChanges: [],
30673
+ undoExpectedFiles: [],
30674
+ undoStatus: "",
30675
+ trackedChangeStatus: "",
30676
+ nativeRequestId: "",
30677
+ queueItemId: "",
30678
+ interruptedDraft: void 0
30679
+ };
30680
+ }
30681
+ function codedError(code, message) {
30682
+ const error = new Error(message);
30683
+ error.code = code;
30684
+ return error;
30685
+ }
30686
+ return { copyRunSnapshot, create };
30687
+ });
30688
+ }).call(globalThis, void 0, void 0, void 0);
30689
+ (function runClassicContentModule82(module, exports, require2) {
29940
30690
  (function initCodexOverleafApplyResultFormatters() {
29941
30691
  "use strict";
29942
30692
  function create(deps = {}) {
@@ -30256,7 +31006,7 @@ ${conclusion}` : `${label} ${conclusion}`;
30256
31006
  window.CodexOverleafApplyResultFormatters = { create };
30257
31007
  })();
30258
31008
  }).call(globalThis, void 0, void 0, void 0);
30259
- (function runClassicContentModule79(module, exports, require2) {
31009
+ (function runClassicContentModule83(module, exports, require2) {
30260
31010
  (function initCodexOverleafModelPickerSupport(root, factory) {
30261
31011
  if (typeof module === "object" && module.exports) {
30262
31012
  module.exports = factory(require2("../shared/models"));
@@ -30273,7 +31023,7 @@ ${conclusion}` : `${label} ${conclusion}`;
30273
31023
  return tiers.includes("standard") ? tiers : ["standard", ...tiers];
30274
31024
  }
30275
31025
  function normalizeReasoningEffortsForSelect(efforts) {
30276
- const allowed = /* @__PURE__ */ new Set(["none", "minimal", "low", "medium", "high", "xhigh"]);
31026
+ const allowed = /* @__PURE__ */ new Set(["none", "minimal", "low", "medium", "high", "xhigh", "max", "ultra"]);
30277
31027
  return Array.from(new Set((Array.isArray(efforts) ? efforts : []).map((effort) => normalizeModelOptionId(effort)).filter((effort) => allowed.has(effort))));
30278
31028
  }
30279
31029
  function formatCompactModelLabel(label) {
@@ -30331,12 +31081,12 @@ ${conclusion}` : `${label} ${conclusion}`;
30331
31081
  const normalized = {
30332
31082
  id,
30333
31083
  label: typeof model?.label === "string" && model.label.length > 0 ? model.label : id,
30334
- reasoningEfforts: Array.isArray(model?.reasoningEfforts) ? model.reasoningEfforts.slice() : [],
31084
+ reasoningEfforts: normalizeReasoningEffortsForSelect(model?.reasoningEfforts),
30335
31085
  reasoningPresentation: typeof model?.reasoningPresentation === "string" ? model.reasoningPresentation : "",
30336
31086
  speedTiers: normalizeSpeedTiersForSelect(model?.speedTiers)
30337
31087
  };
30338
31088
  if (Object.prototype.hasOwnProperty.call(Object(model), "defaultReasoningEffort")) {
30339
- normalized.defaultReasoningEffort = model.defaultReasoningEffort;
31089
+ normalized.defaultReasoningEffort = normalizeModelOptionId(model.defaultReasoningEffort);
30340
31090
  }
30341
31091
  if (Object.prototype.hasOwnProperty.call(Object(model), "defaultSpeedTier")) {
30342
31092
  normalized.defaultSpeedTier = model.defaultSpeedTier;
@@ -30357,7 +31107,7 @@ ${conclusion}` : `${label} ${conclusion}`;
30357
31107
  return api;
30358
31108
  });
30359
31109
  }).call(globalThis, void 0, void 0, void 0);
30360
- (function runClassicContentModule80(module, exports, require2) {
31110
+ (function runClassicContentModule84(module, exports, require2) {
30361
31111
  (function initCodexOverleafModelPicker() {
30362
31112
  "use strict";
30363
31113
  function create(deps = {}) {
@@ -30763,7 +31513,7 @@ ${conclusion}` : `${label} ${conclusion}`;
30763
31513
  if (effort === "none") return tx("Off", "\u5173\u95ED");
30764
31514
  if (effort === "xhigh") return "Max";
30765
31515
  }
30766
- const labels = getLocale() === "zh" ? { none: "\u5173\u95ED", minimal: "\u6700\u5C0F", low: "\u4F4E", medium: "\u4E2D", high: "\u9AD8", xhigh: "\u8D85\u9AD8" } : { none: "Off", minimal: "Minimal", low: "Low", medium: "Medium", high: "High", xhigh: "XHigh" };
31516
+ const labels = getLocale() === "zh" ? { none: "\u5173\u95ED", minimal: "\u6700\u5C0F", low: "\u4F4E", medium: "\u4E2D", high: "\u9AD8", xhigh: "\u8D85\u9AD8", max: "\u6700\u5927", ultra: "\u6781\u9650" } : { none: "Off", minimal: "Minimal", low: "Low", medium: "Medium", high: "High", xhigh: "XHigh", max: "Max", ultra: "Ultra" };
30767
31517
  return labels[effort] || effort || "";
30768
31518
  }
30769
31519
  function resolveSelectedModel() {
@@ -30835,7 +31585,7 @@ ${conclusion}` : `${label} ${conclusion}`;
30835
31585
  window.CodexOverleafModelPicker = { create };
30836
31586
  })();
30837
31587
  }).call(globalThis, void 0, void 0, void 0);
30838
- (function runClassicContentModule81(module, exports, require2) {
31588
+ (function runClassicContentModule85(module, exports, require2) {
30839
31589
  (function initCodexOverleafProjectSessionCleanup() {
30840
31590
  "use strict";
30841
31591
  const FRESH_RUNNING_WINDOW_MS = 30 * 60 * 1e3;
@@ -30935,7 +31685,7 @@ ${conclusion}` : `${label} ${conclusion}`;
30935
31685
  window.CodexOverleafProjectSessionCleanup = { create };
30936
31686
  })();
30937
31687
  }).call(globalThis, void 0, void 0, void 0);
30938
- (function runClassicContentModule82(module, exports, require2) {
31688
+ (function runClassicContentModule86(module, exports, require2) {
30939
31689
  (function initCodexOverleafRecentProjects() {
30940
31690
  "use strict";
30941
31691
  function create(deps = {}) {
@@ -31861,7 +32611,7 @@ ${conclusion}` : `${label} ${conclusion}`;
31861
32611
  window.CodexOverleafRecentProjects = { create };
31862
32612
  })();
31863
32613
  }).call(globalThis, void 0, void 0, void 0);
31864
- (function runClassicContentModule83(module, exports, require2) {
32614
+ (function runClassicContentModule87(module, exports, require2) {
31865
32615
  (function initCodexOverleafOtWarmMirror() {
31866
32616
  "use strict";
31867
32617
  function create(deps = {}) {
@@ -32623,7 +33373,7 @@ ${conclusion}` : `${label} ${conclusion}`;
32623
33373
  applyResults: [],
32624
33374
  nextStep: tr("warmMirrorStaleBlockedNextStep")
32625
33375
  });
32626
- finishRunView(tr("warmMirrorStaleBlockedTitle"), "failed");
33376
+ await finishRunView(tr("warmMirrorStaleBlockedTitle"), "failed");
32627
33377
  return { ok: false };
32628
33378
  }
32629
33379
  if (focusedPartialSnapshot) {
@@ -32716,7 +33466,7 @@ ${conclusion}` : `${label} ${conclusion}`;
32716
33466
  window.CodexOverleafOtWarmMirror = { create };
32717
33467
  })();
32718
33468
  }).call(globalThis, void 0, void 0, void 0);
32719
- (function runClassicContentModule84(module, exports, require2) {
33469
+ (function runClassicContentModule88(module, exports, require2) {
32720
33470
  (function initCodexOverleafWritebackOrchestrator() {
32721
33471
  "use strict";
32722
33472
  let tr;
@@ -32729,7 +33479,6 @@ ${conclusion}` : `${label} ${conclusion}`;
32729
33479
  let appendOperationsPreview;
32730
33480
  let appendPartialWritebackWarning;
32731
33481
  let appendApplyResult;
32732
- let renderDiffReview;
32733
33482
  let renderReadOnlyDiffReview;
32734
33483
  let showPluginConfirm;
32735
33484
  let callPageBridge;
@@ -32766,6 +33515,7 @@ ${conclusion}` : `${label} ${conclusion}`;
32766
33515
  let onMirrorRefreshSettled;
32767
33516
  let writebackSettlement;
32768
33517
  let injectedWritebackSettlement;
33518
+ let assetTransferBroker;
32769
33519
  function buildSettlement(input = {}) {
32770
33520
  return writebackSettlement?.settle instanceof Function ? writebackSettlement.settle(input) : null;
32771
33521
  }
@@ -32793,8 +33543,8 @@ ${conclusion}` : `${label} ${conclusion}`;
32793
33543
  applyResults: [],
32794
33544
  mode: runMode,
32795
33545
  nextStep: tx(
32796
- "Switch to Suggest or Auto only when you want Codex to edit files.",
32797
- "\u53EA\u6709\u5E0C\u671B Codex \u4FEE\u6539\u6587\u4EF6\u65F6\uFF0C\u624D\u9700\u8981\u5207\u6362\u5230\u5EFA\u8BAE\u4FEE\u6539\u6216\u81EA\u52A8\u5199\u5165\u3002"
33546
+ "Switch to Auto only when you want Codex to edit files.",
33547
+ "\u53EA\u6709\u5E0C\u671B Codex \u4FEE\u6539\u6587\u4EF6\u65F6\uFF0C\u624D\u9700\u8981\u5207\u6362\u5230\u81EA\u52A8\u5199\u5165\u3002"
32798
33548
  )
32799
33549
  });
32800
33550
  return {
@@ -32873,50 +33623,6 @@ ${conclusion}` : `${label} ${conclusion}`;
32873
33623
  })
32874
33624
  };
32875
33625
  }
32876
- if (runMode === "confirm") {
32877
- appendRunEvent({
32878
- title: tx(
32879
- `Local Codex produced ${operations.length} change(s). Review the diff before applying.`,
32880
- `\u672C\u5730 Codex \u4EA7\u751F\u4E86 ${operations.length} \u9879\u6539\u52A8\uFF0C\u8BF7\u67E5\u770B\u5DEE\u5F02\u540E\u786E\u8BA4\u3002`
32881
- ),
32882
- status: "running"
32883
- });
32884
- const accepted = await renderDiffReview(visibleSyncChanges);
32885
- if (!accepted.length) {
32886
- appendRunEvent({
32887
- title: tx("Sync cancelled: Overleaf was not modified.", "\u5DF2\u53D6\u6D88\u540C\u6B65\uFF1AOverleaf \u6CA1\u6709\u88AB\u4FEE\u6539\u3002"),
32888
- status: "completed"
32889
- });
32890
- appendCompletionReport({
32891
- conclusion: tx("You cancelled syncing. Local Codex changes were not written back to Overleaf.", "\u4F60\u53D6\u6D88\u4E86\u540C\u6B65\uFF0C\u672C\u5730 Codex \u6539\u52A8\u6CA1\u6709\u5199\u56DE Overleaf\u3002"),
32892
- status: "rejected",
32893
- operations: [],
32894
- applyResults: [],
32895
- mode: runMode,
32896
- nextStep: tx("Run the task again, or switch to Auto if you want changes synced directly.", "\u53EF\u4EE5\u91CD\u65B0\u8FD0\u884C\u4EFB\u52A1\uFF0C\u6216\u5207\u6362\u5230\u81EA\u52A8\u5199\u5165\u540E\u518D\u540C\u6B65\u3002")
32897
- });
32898
- return {
32899
- summaryLine: tx("Sync cancelled", "\u5DF2\u53D6\u6D88\u540C\u6B65"),
32900
- hasSkippedOperations: additionalSkippedEntries.length > 0,
32901
- settlement: buildSettlement({
32902
- operations,
32903
- applyResult: { ok: false, applied: [], skipped: additionalSkippedEntries }
32904
- }),
32905
- audit: buildAuditSummaryFromApply({
32906
- operations,
32907
- applyResults: additionalSkippedEntries.length ? [{ ok: false, applied: [], skipped: additionalSkippedEntries }] : [],
32908
- blockedFiles: additionalSkippedEntries.map((item) => summarizeOperationForAudit(item.operation, item.result, "blocked")),
32909
- resultStatus: "rejected"
32910
- })
32911
- };
32912
- }
32913
- operations = buildSyncApplyOperations(accepted, project);
32914
- const acceptedPathSafety = partitionUnsafeProjectPathOperations(operations);
32915
- if (acceptedPathSafety.skipped.length) {
32916
- additionalSkippedEntries.push(...acceptedPathSafety.skipped);
32917
- operations = acceptedPathSafety.safe;
32918
- }
32919
- }
32920
33626
  const deleteOperations = operations.filter((operation) => operation.type === "delete");
32921
33627
  if (deleteOperations.length) {
32922
33628
  const approved = await showPluginConfirm({
@@ -33014,7 +33720,7 @@ ${conclusion}` : `${label} ${conclusion}`;
33014
33720
  })
33015
33721
  };
33016
33722
  }
33017
- const applied = operations.length ? mergeApplyResultSkipped(await callPageBridge("applyOperations", {
33723
+ const applied = operations.length ? mergeApplyResultSkipped(await assetTransferBroker.applyOperations({
33018
33724
  operations,
33019
33725
  baseFiles: project?.files || [],
33020
33726
  requireReviewing: runRequireReviewing,
@@ -33470,7 +34176,6 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
33470
34176
  appendOperationsPreview,
33471
34177
  appendPartialWritebackWarning,
33472
34178
  appendApplyResult,
33473
- renderDiffReview,
33474
34179
  renderReadOnlyDiffReview,
33475
34180
  showPluginConfirm,
33476
34181
  callPageBridge,
@@ -33504,6 +34209,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
33504
34209
  getState,
33505
34210
  getCurrentRunView
33506
34211
  } = deps);
34212
+ assetTransferBroker = deps.assetTransferBroker;
33507
34213
  onMirrorRefreshSettled = deps.onMirrorRefreshSettled;
33508
34214
  writebackSettlement = deps.writebackSettlement;
33509
34215
  compileAdapter = deps.compileAdapter;
@@ -33516,7 +34222,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
33516
34222
  window.CodexOverleafWritebackOrchestrator = { create };
33517
34223
  })();
33518
34224
  }).call(globalThis, void 0, void 0, void 0);
33519
- (function runClassicContentModule85(module, exports, require2) {
34225
+ (function runClassicContentModule89(module, exports, require2) {
33520
34226
  (function initCodexOverleafRunSettlementPersistence(root, factory) {
33521
34227
  const api = factory();
33522
34228
  if (typeof module === "object" && module.exports) module.exports = api;
@@ -33559,7 +34265,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
33559
34265
  return Object.freeze({ create });
33560
34266
  });
33561
34267
  }).call(globalThis, void 0, void 0, void 0);
33562
- (function runClassicContentModule86(module, exports, require2) {
34268
+ (function runClassicContentModule90(module, exports, require2) {
33563
34269
  (function initPostNavigationSettlementPersistence(root, factory) {
33564
34270
  const api = factory();
33565
34271
  if (typeof module === "object" && module.exports) module.exports = api;
@@ -33651,7 +34357,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
33651
34357
  return Object.freeze({ persist, persistRequired });
33652
34358
  });
33653
34359
  }).call(globalThis, void 0, void 0, void 0);
33654
- (function runClassicContentModule87(module, exports, require2) {
34360
+ (function runClassicContentModule91(module, exports, require2) {
33655
34361
  (function initCodexOverleafPanelMaintenance() {
33656
34362
  "use strict";
33657
34363
  function create(deps = {}) {
@@ -33967,7 +34673,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
33967
34673
  window.CodexOverleafPanelMaintenance = { create };
33968
34674
  })();
33969
34675
  }).call(globalThis, void 0, void 0, void 0);
33970
- (function runClassicContentModule88(module, exports, require2) {
34676
+ (function runClassicContentModule92(module, exports, require2) {
33971
34677
  (function initCodexOverleafUpdateIdle(root) {
33972
34678
  "use strict";
33973
34679
  function create(options2 = {}) {
@@ -34035,7 +34741,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
34035
34741
  root.CodexOverleafUpdateIdle = Object.freeze({ create });
34036
34742
  })(typeof window !== "undefined" ? window : globalThis);
34037
34743
  }).call(globalThis, void 0, void 0, void 0);
34038
- (function runClassicContentModule89(module, exports, require2) {
34744
+ (function runClassicContentModule93(module, exports, require2) {
34039
34745
  (function initCodexOverleafUpdateNotice(root, factory) {
34040
34746
  if (typeof module === "object" && module.exports) {
34041
34747
  module.exports = factory(require2("../shared/managedUpdateProjection"));
@@ -34479,7 +35185,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
34479
35185
  return Object.freeze({ mount });
34480
35186
  });
34481
35187
  }).call(globalThis, void 0, void 0, void 0);
34482
- (function runClassicContentModule90(module, exports, require2) {
35188
+ (function runClassicContentModule94(module, exports, require2) {
34483
35189
  (function initCodexOverleafContentRuntime(root) {
34484
35190
  "use strict";
34485
35191
  function init(dependencies2) {
@@ -34529,7 +35235,6 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
34529
35235
  "codex.providers.clear-secret",
34530
35236
  "codex.providers.delete",
34531
35237
  "task.run",
34532
- "task.confirm",
34533
35238
  "mirror.sync",
34534
35239
  "mirror.patchFiles",
34535
35240
  "mirror.confirmWriteback",
@@ -34639,6 +35344,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
34639
35344
  callPageBridge,
34640
35345
  getCurrentProjectId,
34641
35346
  getCurrentProjectReferenceFiles,
35347
+ getCurrentProjectMathSources,
34642
35348
  showPluginToast,
34643
35349
  recordRenderingDiagnostic: (detail) => appendTechnicalEvent({ type: "rendering.diagnostic", detail })
34644
35350
  });
@@ -34851,8 +35557,26 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
34851
35557
  openProjectFileForFailure,
34852
35558
  openStorageSettings
34853
35559
  } = panelMaintenance;
35560
+ const sessionForkController = Modules.SessionForkController.create({
35561
+ SessionState: Modules.SessionState,
35562
+ getState: () => state,
35563
+ setState: (next) => {
35564
+ state = next;
35565
+ },
35566
+ sendBackgroundNative,
35567
+ saveState,
35568
+ applyStateToPanel,
35569
+ showPluginToast,
35570
+ tr
35571
+ });
35572
+ const runResultActions = Modules.RunResultActions.create({
35573
+ tr,
35574
+ getLocale,
35575
+ forkRunFromNode: sessionForkController.forkRunFromNode
35576
+ });
34854
35577
  const runTimelineView = Modules.RunTimelineView.create({
34855
35578
  RunGuidanceView: Modules.RunGuidanceView,
35579
+ RunResultActions: runResultActions,
34856
35580
  tr,
34857
35581
  tx,
34858
35582
  getLocale,
@@ -34963,6 +35687,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
34963
35687
  getCurrentProjectId,
34964
35688
  saveStateSoon
34965
35689
  });
35690
+ const assetTransferBroker = Modules.AssetTransferBroker.create({ callPageBridge, sendBackgroundNative });
34966
35691
  const writebackOrchestrator = Modules.WritebackOrchestrator.create({
34967
35692
  tr,
34968
35693
  tx,
@@ -34973,7 +35698,6 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
34973
35698
  appendOperationsPreview,
34974
35699
  appendPartialWritebackWarning,
34975
35700
  appendApplyResult,
34976
- renderDiffReview,
34977
35701
  renderReadOnlyDiffReview,
34978
35702
  showPluginConfirm,
34979
35703
  callPageBridge,
@@ -35003,6 +35727,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
35003
35727
  confirmBinaryOperations,
35004
35728
  filterSyncChangesByOperations,
35005
35729
  writebackController,
35730
+ assetTransferBroker,
35006
35731
  writebackSettlement: WritebackSettlement,
35007
35732
  compileAdapter: Modules.CompileAdapter,
35008
35733
  RUN_SNAPSHOT_ZIP_TIMEOUT_MS,
@@ -35867,9 +36592,6 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
35867
36592
  if (mode === "ask") {
35868
36593
  return "Ask";
35869
36594
  }
35870
- if (mode === "confirm") {
35871
- return "Confirm";
35872
- }
35873
36595
  if (mode === "auto") {
35874
36596
  return "Auto";
35875
36597
  }
@@ -36184,7 +36906,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
36184
36906
  if (!useExistingMirror) {
36185
36907
  appendLog(formatProjectSnapshotUserLog(project));
36186
36908
  }
36187
- currentRunView.projectFiles = captureProjectReferenceFiles(project);
36909
+ persistCurrentProjectReferenceFiles(project);
36188
36910
  const snapshotWarnings = useExistingMirror ? { blocking: [], nonBlocking: [] } : getProjectSnapshotWarnings(project);
36189
36911
  const warmMirrorReuse = useExistingMirror ? warmStart : await awaitRunStep(resolveWarmMirrorReuse(project, {
36190
36912
  snapshotWarnings,
@@ -36222,7 +36944,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
36222
36944
  skippedFiles: [],
36223
36945
  blockedFiles: snapshotWarnings.blocking.map((reason) => ({ path: "project", reason }))
36224
36946
  });
36225
- finishRunView(tx("Blocked: full project was not read", "\u5DF2\u963B\u6B62\uFF1A\u6CA1\u6709\u8BFB\u5230\u5B8C\u6574\u9879\u76EE"), "failed");
36947
+ await finishRunView(tx("Blocked: full project was not read", "\u5DF2\u963B\u6B62\uFF1A\u6CA1\u6709\u8BFB\u5230\u5B8C\u6574\u9879\u76EE"), "failed");
36226
36948
  return;
36227
36949
  }
36228
36950
  if (warmMirrorReuse.useExistingMirror) {
@@ -36295,7 +37017,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
36295
37017
  reason: finding.detectorId || "sensitive"
36296
37018
  }))
36297
37019
  });
36298
- finishRunView(tx("Blocked: sensitive content review required", "\u5DF2\u963B\u6B62\uFF1A\u9700\u8981\u5904\u7406\u654F\u611F\u5185\u5BB9"), "failed");
37020
+ await finishRunView(tx("Blocked: sensitive content review required", "\u5DF2\u963B\u6B62\uFF1A\u9700\u8981\u5904\u7406\u654F\u611F\u5185\u5BB9"), "failed");
36299
37021
  return;
36300
37022
  }
36301
37023
  if (sensitiveFindings.findings.length) {
@@ -36330,7 +37052,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
36330
37052
  return;
36331
37053
  }
36332
37054
  project = staleRetry.project;
36333
- currentRunView.projectFiles = captureProjectReferenceFiles(project);
37055
+ persistCurrentProjectReferenceFiles(project);
36334
37056
  useExistingMirror = false;
36335
37057
  fileOverlays = null;
36336
37058
  otWarmStart = false;
@@ -36384,14 +37106,14 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
36384
37106
  } else {
36385
37107
  appendRunEvent({ title: tx("Cancelled: user chose not to create a new thread.", "\u5DF2\u53D6\u6D88\uFF1A\u7528\u6237\u9009\u62E9\u4E0D\u65B0\u5EFA\u7EBF\u7A0B\u3002"), status: "rejected" });
36386
37108
  await finalizeAuditRecord(runAuditDraft, { resultStatus: "rejected" });
36387
- finishRunView(tx("Cancelled", "\u5DF2\u53D6\u6D88"), "rejected");
37109
+ await finishRunView(tx("Cancelled", "\u5DF2\u53D6\u6D88"), "rejected");
36388
37110
  return;
36389
37111
  }
36390
37112
  }
36391
37113
  if (!response.ok) {
36392
37114
  if (runCancellationRequested || isRunCancellationError(response.error)) {
36393
37115
  appendRunCancelledReport();
36394
- finishRunView(tx("Cancelled", "\u5DF2\u4E2D\u65AD"), "rejected");
37116
+ await finishRunView(tx("Cancelled", "\u5DF2\u4E2D\u65AD"), "rejected");
36395
37117
  void finalizeAuditRecord(runAuditDraft, { resultStatus: "cancelled" });
36396
37118
  return;
36397
37119
  }
@@ -36456,7 +37178,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
36456
37178
  sensitiveFindings: sensitiveFindings.findings,
36457
37179
  blockedFiles: [{ path: "codex.run", reason: response.error?.code || response.error?.message || "native_error" }]
36458
37180
  });
36459
- finishRunView(response.error?.code === "project_locked" ? tx("Codex task already running", "Codex \u4EFB\u52A1\u6B63\u5728\u8FD0\u884C") : tx("Local Codex error", "\u672C\u5730 Codex \u9519\u8BEF"), "failed");
37181
+ await finishRunView(response.error?.code === "project_locked" ? tx("Codex task already running", "Codex \u4EFB\u52A1\u6B63\u5728\u8FD0\u884C") : tx("Local Codex error", "\u672C\u5730 Codex \u9519\u8BEF"), "failed");
36460
37182
  return;
36461
37183
  }
36462
37184
  throwIfRunCancellationRequested();
@@ -36497,7 +37219,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
36497
37219
  sensitiveFindings: sensitiveFindings.findings,
36498
37220
  blockedFiles: [{ path: "codex.run", reason: "codex_no_usable_result" }]
36499
37221
  });
36500
- finishRunView(tx("Local Codex returned nothing usable", "\u672C\u5730 Codex \u6CA1\u6709\u8FD4\u56DE\u53EF\u7528\u7ED3\u679C"), "failed");
37222
+ await finishRunView(tx("Local Codex returned nothing usable", "\u672C\u5730 Codex \u6CA1\u6709\u8FD4\u56DE\u53EF\u7528\u7ED3\u679C"), "failed");
36501
37223
  return;
36502
37224
  }
36503
37225
  const writebackProject = useExistingMirror ? mergeProjectWithSyncChangeBaseFiles(project, syncChanges) : project;
@@ -36517,7 +37239,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
36517
37239
  sensitiveFindings: sensitiveFindings.findings,
36518
37240
  resultStatus: syncOutcome.hasSkippedOperations ? "completed_with_skips" : "completed"
36519
37241
  });
36520
- finishRunView(
37242
+ await finishRunView(
36521
37243
  syncOutcome.hasSkippedOperations ? tx("Sync completed with skipped items", "\u540C\u6B65\u5B8C\u6210\u4F46\u6709\u8DF3\u8FC7\u9879") : tx("Sync completed", "\u540C\u6B65\u5B8C\u6210"),
36522
37244
  syncOutcome.hasSkippedOperations ? "failed" : "completed"
36523
37245
  );
@@ -36587,7 +37309,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
36587
37309
  } catch (error) {
36588
37310
  if (runCancellationRequested || isRunCancellationError(error)) {
36589
37311
  appendRunCancelledReport();
36590
- finishRunView(tx("Cancelled", "\u5DF2\u4E2D\u65AD"), "rejected");
37312
+ await finishRunView(tx("Cancelled", "\u5DF2\u4E2D\u65AD"), "rejected");
36591
37313
  void finalizeAuditRecord(runAuditDraft, { resultStatus: "cancelled" });
36592
37314
  return;
36593
37315
  }
@@ -36627,7 +37349,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
36627
37349
  resultStatus: "failed",
36628
37350
  blockedFiles: [{ path: "task", reason: error.message }]
36629
37351
  });
36630
- finishRunView(tx("Task failed", "\u4EFB\u52A1\u5931\u8D25"), "failed");
37352
+ await finishRunView(tx("Task failed", "\u4EFB\u52A1\u5931\u8D25"), "failed");
36631
37353
  } finally {
36632
37354
  const settledView = currentRunView;
36633
37355
  const settledRecord = settledView ? findRunRecord(settledView.recordId, settledView.sessionId) : null;
@@ -36700,7 +37422,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
36700
37422
  if (runCancellationRequested || isRunCancellationError(response.error)) {
36701
37423
  appendRunCancelledReport();
36702
37424
  await finalizeAuditRecord(runAuditDraft, { resultStatus: "cancelled" });
36703
- finishRunView(tx("Cancelled", "\u5DF2\u4E2D\u65AD"), "rejected");
37425
+ await finishRunView(tx("Cancelled", "\u5DF2\u4E2D\u65AD"), "rejected");
36704
37426
  return;
36705
37427
  }
36706
37428
  const translated = translateRawError(response.error.message, { mode: submittedMode, locale: getLocale() });
@@ -36728,7 +37450,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
36728
37450
  resultStatus: "failed",
36729
37451
  blockedFiles: [{ path: "skill-installer", reason: response.error?.code || response.error?.message || "native_error" }]
36730
37452
  });
36731
- finishRunView(tx("Skill installer failed", "Skill installer \u5931\u8D25"), "failed");
37453
+ await finishRunView(tx("Skill installer failed", "Skill installer \u5931\u8D25"), "failed");
36732
37454
  return;
36733
37455
  }
36734
37456
  const assistantMessage = response.result?.assistantMessage || getAssistantAnswerForCurrentRun();
@@ -36741,7 +37463,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
36741
37463
  mode: submittedMode
36742
37464
  });
36743
37465
  await finalizeAuditRecord(runAuditDraft, { resultStatus: "completed" });
36744
- finishRunView(tx("Skill installer completed", "Skill installer \u5DF2\u5B8C\u6210"), "completed");
37466
+ await finishRunView(tx("Skill installer completed", "Skill installer \u5DF2\u5B8C\u6210"), "completed");
36745
37467
  const runSessionForHistory = findSessionById(runSessionId) || getActiveSession(state);
36746
37468
  const rawAssistantMessage = assistantMessage;
36747
37469
  const rawSyncOutcome = { summaryLine: "skill installer completed" };
@@ -36832,7 +37554,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
36832
37554
  nextStep
36833
37555
  });
36834
37556
  const finishTitle = requireReviewing ? tx("Not started: could not enable Track Changes", "\u672A\u5F00\u59CB\uFF1A\u65E0\u6CD5\u5F00\u542F\u7559\u75D5") : tx("Not started: could not switch to Editing", "\u672A\u5F00\u59CB\uFF1A\u65E0\u6CD5\u5207\u6362\u5230 Editing");
36835
- finishRunView(finishTitle, "failed");
37557
+ await finishRunView(finishTitle, "failed");
36836
37558
  return {
36837
37559
  ok: false,
36838
37560
  reason,
@@ -37874,9 +38596,6 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
37874
38596
  function createDiffReviewElement(syncChanges, options2 = {}) {
37875
38597
  return diffReviewPanel.createDiffReviewElement(syncChanges, options2);
37876
38598
  }
37877
- function renderDiffReview(syncChanges) {
37878
- return diffReviewPanel.renderDiffReview(syncChanges);
37879
- }
37880
38599
  function renderReadOnlyDiffReview(syncChanges, title = tr("diffWrittenChangesTitle")) {
37881
38600
  return diffReviewPanel.renderReadOnlyDiffReview(syncChanges, title);
37882
38601
  }
@@ -38447,76 +39166,10 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
38447
39166
  mode,
38448
39167
  operations: [],
38449
39168
  applyResults: [],
38450
- nextStep: tx("Continue the conversation, or switch to Suggest/Auto to let Codex edit files.", "\u53EF\u4EE5\u7EE7\u7EED\u8FFD\u95EE\uFF0C\u6216\u5207\u6362\u5230\u5EFA\u8BAE\u4FEE\u6539/\u81EA\u52A8\u5199\u5165\u540E\u8BA9 Codex \u4FEE\u6539\u6587\u4EF6\u3002")
39169
+ nextStep: tx("Continue the conversation, or switch to Auto to let Codex edit files.", "\u53EF\u4EE5\u7EE7\u7EED\u8FFD\u95EE\uFF0C\u6216\u5207\u6362\u5230\u81EA\u52A8\u5199\u5165\u540E\u8BA9 Codex \u4FEE\u6539\u6587\u4EF6\u3002")
38451
39170
  });
38452
39171
  return { status: tr("modeAsk"), summaryLine: summaryLine2 };
38453
39172
  }
38454
- if (result.status === "requires_task_confirmation") {
38455
- appendPlannedChangeSummary(result.summary, tx("Preparing changes", "\u51C6\u5907\u4FEE\u6539"));
38456
- const approved = await showPluginConfirm({
38457
- title: tx("Apply these changes?", "\u5E94\u7528\u8FD9\u4E9B\u4FEE\u6539\uFF1F"),
38458
- message: formatSummary(tx("Change Summary", "\u4FEE\u6539\u6458\u8981"), result.summary),
38459
- confirmLabel: tx("Apply changes", "\u5E94\u7528\u4FEE\u6539"),
38460
- cancelLabel: tr("confirmDefaultCancel")
38461
- });
38462
- if (!approved) {
38463
- appendLog(tx("Cancelled: Codex did not write any files.", "\u5DF2\u53D6\u6D88\uFF1ACodex \u6CA1\u6709\u5199\u5165\u4EFB\u4F55\u6587\u4EF6\u3002"));
38464
- const summaryLine3 = appendChangeSummary({ notes, summary: result.summary, status: "rejected" });
38465
- appendCompletionReport({
38466
- conclusion: tx("You cancelled this change. Codex did not write files.", "\u4F60\u53D6\u6D88\u4E86\u8FD9\u8F6E\u4FEE\u6539\uFF0CCodex \u6CA1\u6709\u5199\u5165\u6587\u4EF6\u3002"),
38467
- status: "rejected",
38468
- notes,
38469
- summary: result.summary,
38470
- userReport: result.userReport,
38471
- mode,
38472
- operations: [],
38473
- applyResults: [],
38474
- nextStep: tx("Adjust the task and run again, or switch to Ask first so Codex can explain the plan.", "\u53EF\u4EE5\u8C03\u6574\u4EFB\u52A1\u63CF\u8FF0\u540E\u91CD\u65B0\u8FD0\u884C\uFF0C\u6216\u5207\u5230\u53EA\u95EE\u4E0D\u6539\u5148\u8BA9 Codex \u89E3\u91CA\u65B9\u6848\u3002")
38475
- });
38476
- return { status: "rejected", summaryLine: summaryLine3 };
38477
- }
38478
- const confirmed = result.planId ? await sendNative({ method: "task.confirm", params: { planId: result.planId } }) : { ok: true, result: { operations: result.operations || [] } };
38479
- if (!confirmed.ok) {
38480
- appendLog(`Confirm failed: ${confirmed.error.message}`);
38481
- const summaryLine3 = appendChangeSummary({ notes, operations: [], status: "confirm failed" });
38482
- appendCompletionReport({
38483
- conclusion: tx("No writable changes were returned after confirmation.", "\u786E\u8BA4\u540E\u6CA1\u6709\u62FF\u5230\u53EF\u5199\u5165\u7684\u4FEE\u6539\u3002"),
38484
- status: "confirm failed",
38485
- notes,
38486
- userReport: result.userReport,
38487
- mode,
38488
- operations: [],
38489
- applyResults: [],
38490
- nextStep: confirmed.error.message
38491
- });
38492
- return { status: "confirm failed", summaryLine: summaryLine3 };
38493
- }
38494
- const operations2 = confirmed.result.operations || [];
38495
- appendOperationsPreview(operations2, tx("Confirmed; preparing to write", "\u7528\u6237\u5DF2\u786E\u8BA4\uFF0C\u51C6\u5907\u5199\u5165"));
38496
- const applied2 = await applyTaskOperations(project, operations2, { allowHighRisk: true });
38497
- appendApplyResult(applied2);
38498
- recordUndoFromApply(project, applied2);
38499
- const summaryLine2 = appendChangeSummary({
38500
- notes,
38501
- operations: operations2,
38502
- applyResults: [applied2],
38503
- status: "confirmed and applied"
38504
- });
38505
- appendCompletionReport({
38506
- conclusion: notes || tx("Changes were written after your confirmation.", "\u5DF2\u6309\u4F60\u7684\u786E\u8BA4\u5199\u5165\u4FEE\u6539\u3002"),
38507
- status: "confirmed and applied",
38508
- notes,
38509
- userReport: result.userReport,
38510
- mode,
38511
- operations: operations2,
38512
- applyResults: [applied2]
38513
- });
38514
- return {
38515
- status: "confirmed and applied",
38516
- summaryLine: summaryLine2,
38517
- hasSkippedOperations: hasSkippedApplyOperations([applied2])
38518
- };
38519
- }
38520
39173
  if (result.status === "delete_plan_required") {
38521
39174
  const operations2 = result.operations || [];
38522
39175
  const applyResults = [];
@@ -38588,7 +39241,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
38588
39241
  }
38589
39242
  const operations = result.operations || [];
38590
39243
  appendOperationsPreview(operations, tx("Preparing to write", "\u51C6\u5907\u5199\u5165"));
38591
- const applied = await applyTaskOperations(project, operations, { allowHighRisk: mode === "confirm" });
39244
+ const applied = await applyTaskOperations(project, operations);
38592
39245
  appendApplyResult(applied);
38593
39246
  recordUndoFromApply(project, applied);
38594
39247
  appendLog(mode === "auto" ? tx("Auto write task completed.", "\u81EA\u52A8\u5199\u5165\u4EFB\u52A1\u5B8C\u6210\u3002") : tx("Task completed.", "\u4EFB\u52A1\u5B8C\u6210\u3002"));
@@ -38856,9 +39509,6 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
38856
39509
  if (mode === "ask") {
38857
39510
  return tr("modeAsk");
38858
39511
  }
38859
- if (mode === "confirm") {
38860
- return tr("modeConfirm");
38861
- }
38862
39512
  if (mode === "auto") {
38863
39513
  return tr("modeAuto");
38864
39514
  }
@@ -38869,8 +39519,6 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
38869
39519
  const labels = {
38870
39520
  completed: tx("Completed", "\u5DF2\u5B8C\u6210"),
38871
39521
  rejected: tx("Cancelled", "\u5DF2\u53D6\u6D88"),
38872
- "confirm failed": tx("Confirmation failed", "\u786E\u8BA4\u5931\u8D25"),
38873
- "confirmed and applied": tx("Suggested changes applied", "\u5DF2\u5E94\u7528\u5EFA\u8BAE\u4FEE\u6539"),
38874
39522
  "applied with delete plan": tx("Applied with confirmed deletes", "\u5DF2\u5E94\u7528\u5E76\u5220\u9664\u786E\u8BA4\u9879"),
38875
39523
  "applied without deletes": tx("Applied without deletes", "\u5DF2\u5E94\u7528\u975E\u5220\u9664\u4FEE\u6539"),
38876
39524
  "\u53EA\u95EE\u4E0D\u6539": tr("modeAsk")
@@ -39246,6 +39894,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
39246
39894
  speedTier: prefs.speedTier || "",
39247
39895
  mode: prefs.mode || "",
39248
39896
  locale: prefs.locale || "",
39897
+ theme: ["dark", "light", "auto"].includes(prefs.theme) ? prefs.theme : "dark",
39249
39898
  requireReviewing: prefs.requireReviewing !== false,
39250
39899
  autoRecompile: prefs.autoRecompile !== false,
39251
39900
  loadCodexLocalSkills: prefs.loadCodexLocalSkills !== false,
@@ -39268,7 +39917,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
39268
39917
  history: Array.isArray(session.history) ? session.history : [],
39269
39918
  task: typeof session.task === "string" ? session.task : "",
39270
39919
  pendingInputs: Array.isArray(session.pendingInputs) ? session.pendingInputs : [],
39271
- mode: session.mode || prefs.mode || "confirm",
39920
+ mode: session.mode || prefs.mode || "ask",
39272
39921
  providerId: session.providerId || "builtin",
39273
39922
  model: session.model || prefs.model || "gpt-5.4",
39274
39923
  reasoningEffort: session.reasoningEffort || prefs.reasoningEffort || "high",
@@ -39293,6 +39942,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
39293
39942
  reasoningEffort: fallback.reasoningEffort || "",
39294
39943
  speedTier: fallback.speedTier || "",
39295
39944
  locale: fallback.locale || "",
39945
+ theme: ["dark", "light", "auto"].includes(fallback.theme) ? fallback.theme : "dark",
39296
39946
  requireReviewing: fallback.requireReviewing !== false,
39297
39947
  autoOpen: fallback.autoOpen !== false,
39298
39948
  loadCodexLocalSkills: fallback.loadCodexLocalSkills !== false,
@@ -39555,7 +40205,10 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
39555
40205
  saveStateSoon();
39556
40206
  return;
39557
40207
  }
39558
- if (event?.target?.matches?.("[data-speed]")) renderReasoningOptions(getRenderedModelEntries());
40208
+ if (event?.target?.matches?.("[data-speed]")) {
40209
+ state.speedTier = event.target.value || "standard";
40210
+ renderReasoningOptions(getRenderedModelEntries());
40211
+ }
39559
40212
  renderSpeedOptions(getRenderedModelEntries());
39560
40213
  readPanelInputs();
39561
40214
  renderModelConfigChoices();
@@ -39577,7 +40230,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
39577
40230
  }));
39578
40231
  }
39579
40232
  async function selectMode(mode) {
39580
- if (!["ask", "confirm", "auto"].includes(mode)) {
40233
+ if (!["ask", "auto"].includes(mode)) {
39581
40234
  return;
39582
40235
  }
39583
40236
  const modeSelect = panel?.querySelector("[data-mode]");
@@ -39824,7 +40477,11 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
39824
40477
  events: root2.querySelector("[data-run-events]"),
39825
40478
  report: root2.querySelector("[data-run-report]"),
39826
40479
  status: root2.querySelector("[data-run-status]"),
39827
- projectFiles: captureProjectReferenceFiles(arguments[0]?.project),
40480
+ // A run starts before warm-mirror resolution has produced its lightweight
40481
+ // project snapshot. Seed references from the already-prefetched project
40482
+ // inventory so early stream events and fast Ask responses can still
40483
+ // resolve project-relative locations.
40484
+ projectFiles: getCurrentProjectReferenceFiles(),
39828
40485
  startedAt: Date.now(),
39829
40486
  queueItemId,
39830
40487
  nativeRequestId: "",
@@ -39841,7 +40498,7 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
39841
40498
  session.lastActivityAt = updatedAt;
39842
40499
  return updatedAt;
39843
40500
  }
39844
- function finishRunView(text, status) {
40501
+ async function finishRunView(text, status) {
39845
40502
  if (!currentRunView) {
39846
40503
  return;
39847
40504
  }
@@ -39859,7 +40516,8 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
39859
40516
  runGuidanceController.settleView(currentRunView);
39860
40517
  const navigationDivergent = currentRunView.runProjectId && activeProjectId !== currentRunView.runProjectId;
39861
40518
  if (!navigationDivergent) {
39862
- saveStateSoon();
40519
+ await flushQueuedSaveState().catch(() => {
40520
+ });
39863
40521
  }
39864
40522
  renderSessionList();
39865
40523
  }
@@ -40129,6 +40787,37 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
40129
40787
  }
40130
40788
  return nextWidth;
40131
40789
  }
40790
+ function getCurrentProjectMathSources() {
40791
+ const sources = [];
40792
+ const seen = /* @__PURE__ */ new Set();
40793
+ let remainingChars = 256 * 1024;
40794
+ const add = (item) => {
40795
+ if (!item || typeof item !== "object" || typeof item.content !== "string") return;
40796
+ const path = normalizeReferencePathForRuntime(item.path || item.filePath || "");
40797
+ if (!path || seen.has(path) || hasUnsafeRuntimePathSegments(path) || !/\.(?:tex|sty|cls|ltx)$/i.test(path) || remainingChars <= 0) return;
40798
+ const content = item.content.slice(0, Math.min(64 * 1024, remainingChars));
40799
+ remainingChars -= content.length;
40800
+ seen.add(path);
40801
+ sources.push({ path, content });
40802
+ };
40803
+ for (const collection of [
40804
+ currentRunView?.projectFiles,
40805
+ currentRunView?.files,
40806
+ currentRunView?.project?.files,
40807
+ currentRunView?.snapshot?.files,
40808
+ currentRunView?.projectSnapshot?.files,
40809
+ currentRunView?.contextFiles,
40810
+ state?.projectFiles,
40811
+ state?.files,
40812
+ state?.project?.files,
40813
+ state?.snapshot?.files,
40814
+ state?.projectSnapshot?.files,
40815
+ state?.contextFiles
40816
+ ]) {
40817
+ if (Array.isArray(collection)) collection.forEach(add);
40818
+ }
40819
+ return sources;
40820
+ }
40132
40821
  function getCurrentProjectReferenceFiles() {
40133
40822
  const files = [];
40134
40823
  const seen = /* @__PURE__ */ new Set();
@@ -40169,7 +40858,10 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
40169
40858
  value.forEach((item) => addFile(item, true));
40170
40859
  }
40171
40860
  };
40861
+ const activeSession = typeof getActiveSession === "function" ? getActiveSession(state) : null;
40172
40862
  addFiles(currentRunView?.projectFiles);
40863
+ addFiles(activeSession?.projectReferenceFiles);
40864
+ addFiles(contextTrayController?.getContextProject?.()?.files);
40173
40865
  addFiles(currentRunView?.files);
40174
40866
  addFiles(currentRunView?.project?.files);
40175
40867
  addFiles(currentRunView?.snapshot?.files);
@@ -40183,13 +40875,24 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
40183
40875
  addFiles(state?.contextFiles);
40184
40876
  addTextPaths(state?.focusFiles);
40185
40877
  addTextPaths(state?.session?.focusFiles);
40186
- const activeSession = typeof getActiveSession === "function" ? getActiveSession(state) : null;
40187
40878
  addTextPaths(activeSession?.focusFiles);
40188
40879
  for (const session of Array.isArray(state?.sessions) ? state.sessions : []) {
40880
+ addFiles(session?.projectReferenceFiles);
40189
40881
  addTextPaths(session?.focusFiles);
40190
40882
  }
40191
40883
  return files;
40192
40884
  }
40885
+ function persistCurrentProjectReferenceFiles(project) {
40886
+ const projectFiles = captureProjectReferenceFiles(project);
40887
+ if (currentRunView) {
40888
+ currentRunView.projectFiles = projectFiles;
40889
+ }
40890
+ if (getActiveSession(state)) {
40891
+ state = updateActiveSession(state, { projectReferenceFiles: projectFiles });
40892
+ saveStateSoon();
40893
+ }
40894
+ return projectFiles;
40895
+ }
40193
40896
  function captureProjectReferenceFiles(project) {
40194
40897
  const result = [];
40195
40898
  const seen = /* @__PURE__ */ new Set();
@@ -40583,7 +41286,12 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
40583
41286
  record.undoOperations = [];
40584
41287
  record.undoBaseFiles = [];
40585
41288
  record.undoTrackedChanges = combinedTrackedChanges;
40586
- record.undoExpectedFiles = selectExpectedFilesForTrackedUndo(project, combinedAppliedOperations, combinedTrackedChanges);
41289
+ record.undoExpectedFiles = selectExpectedFilesForTrackedUndo(
41290
+ project,
41291
+ combinedAppliedOperations,
41292
+ combinedTrackedChanges,
41293
+ record.undoExpectedFiles
41294
+ );
40587
41295
  record.undoStatus = "";
40588
41296
  record.partialWriteback = skippedEntries.length > 0;
40589
41297
  if (combinedTrackedChanges.length) {
@@ -40626,7 +41334,12 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
40626
41334
  record.undoOperations = checkpoint.undoOperations;
40627
41335
  record.undoBaseFiles = checkpoint.undoBaseFiles;
40628
41336
  record.undoTrackedChanges = [];
40629
- record.undoExpectedFiles = selectExpectedFilesForTrackedUndo(project, combinedAppliedOperations, []);
41337
+ record.undoExpectedFiles = selectExpectedFilesForTrackedUndo(
41338
+ project,
41339
+ combinedAppliedOperations,
41340
+ [],
41341
+ record.undoExpectedFiles
41342
+ );
40630
41343
  record.undoStatus = "";
40631
41344
  record.partialWriteback = skippedEntries.length > 0;
40632
41345
  refreshRunCardControls(record.id);
@@ -40644,8 +41357,13 @@ ${tx("Writeback note: Codex could not confirm any Overleaf write result entries,
40644
41357
  function normalizeApplyTrackedChanges(changes = []) {
40645
41358
  return WritebackSettlement.normalizeApplyTrackedChanges(changes);
40646
41359
  }
40647
- function selectExpectedFilesForTrackedUndo(project, operations = [], trackedChanges = []) {
40648
- return WritebackSettlement.selectExpectedFilesForTrackedUndo(project, operations, trackedChanges);
41360
+ function selectExpectedFilesForTrackedUndo(project, operations = [], trackedChanges = [], previousExpectedFiles = []) {
41361
+ return WritebackSettlement.selectExpectedFilesForTrackedUndo(
41362
+ project,
41363
+ operations,
41364
+ trackedChanges,
41365
+ previousExpectedFiles
41366
+ );
40649
41367
  }
40650
41368
  function buildTrackedUndoPostFiles(run) {
40651
41369
  const expectedFiles = Array.isArray(run?.undoExpectedFiles) ? run.undoExpectedFiles : [];
@@ -41238,7 +41956,7 @@ Reason: ${item.reason || "No reason provided"}`),
41238
41956
  root.CodexOverleafContentRuntime = { init };
41239
41957
  })(typeof window !== "undefined" ? window : globalThis);
41240
41958
  }).call(globalThis, void 0, void 0, void 0);
41241
- (function runClassicContentModule91(module, exports, require2) {
41959
+ (function runClassicContentModule95(module, exports, require2) {
41242
41960
  (function initCodexOverleafLegacyGlobalRegistry(root, factory) {
41243
41961
  "use strict";
41244
41962
  const api = factory();
@@ -41254,6 +41972,7 @@ Reason: ${item.reason || "No reason provided"}`),
41254
41972
  "ActiveTurnControl",
41255
41973
  "AgentTranscript",
41256
41974
  "ApplyResultFormatters",
41975
+ "AssetTransferBroker",
41257
41976
  "AuditRecords",
41258
41977
  "Compatibility",
41259
41978
  "ComposerAttachments",
@@ -41292,12 +42011,14 @@ Reason: ${item.reason || "No reason provided"}`),
41292
42011
  "RunGuidanceController",
41293
42012
  "RunInputQueue",
41294
42013
  "RunQueueScheduler",
42014
+ "RunResultActions",
41295
42015
  "RunSettlementPersistence",
41296
42016
  "RunTimelineView",
41297
42017
  "ScopedPersistenceCoordinator",
41298
42018
  "ScopedPersistenceTransaction",
41299
42019
  "SensitiveScan",
41300
42020
  "SessionManager",
42021
+ "SessionForkController",
41301
42022
  "SessionPanel",
41302
42023
  "SessionPersistence",
41303
42024
  "SessionState",