codex-overleaf-link 2.3.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -23
- package/extension/bootstrap/manifest.template.json +1 -1
- package/extension/src/background.js +20 -0
- package/extension/src/content/composerPanel.js +0 -2
- package/extension/src/content/contentRuntime.js +108 -110
- package/extension/src/content/generated/content.bundle.js +566 -331
- package/extension/src/content/generated/content.bundle.meta.json +4 -3
- package/extension/src/content/markdownText.js +12 -10
- package/extension/src/content/mathText.js +155 -9
- package/extension/src/content/nativeCompatibilityController.js +2 -2
- package/extension/src/content/otWarmMirror.js +1 -1
- package/extension/src/content/runTimelineView.js +6 -0
- package/extension/src/content/writebackOrchestrator.js +2 -49
- package/extension/src/page/trackedChangesLifecycle.js +10 -4
- package/extension/src/page/writebackRouter.js +6 -2
- package/extension/src/shared/agentTranscript.js +10 -3
- package/extension/src/shared/compatibility.js +1 -1
- package/extension/src/shared/i18n.js +2 -4
- package/extension/src/shared/pageRpcContract.js +2 -2
- package/extension/src/shared/runExecutionSnapshot.js +14 -4
- package/extension/src/shared/runExecutionSnapshotCodec.js +5 -2
- package/extension/src/shared/scopedPersistenceQueuePolicy.js +20 -1
- package/extension/src/shared/scopedPersistenceReceipt.js +60 -0
- package/extension/src/shared/scopedPersistenceTransaction.js +50 -47
- package/extension/src/shared/sessionState.js +46 -11
- package/extension/src/shared/storageDb.js +6 -5
- package/extension/src/shared/writebackOperationEvidence.js +16 -6
- package/extension/src/shared/writebackSettlement.js +28 -6
- package/extension/styles/panel.css +18 -8
- package/native-host/src/codexPromptAssembly.js +1 -1
- package/native-host/src/taskRunnerRuntime.js +11 -81
- package/native-host/src/updateManager.js +36 -1
- package/package.json +1 -1
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
const { buildCodexRuntimeEvent } = require('./codexRuntimeIdentity');
|
|
4
4
|
|
|
5
5
|
const { spawn } = require('node:child_process');
|
|
6
|
-
const crypto = require('node:crypto');
|
|
7
6
|
const { buildOperationSummary, splitDeletePlan } = require('../../extension/src/shared/summary');
|
|
8
7
|
const {
|
|
9
8
|
MIN_COMPATIBLE_EXTENSION_VERSION,
|
|
@@ -40,8 +39,6 @@ const activeRunEntries = new Map();
|
|
|
40
39
|
// Overleaf tab was reloaded — the requestId lived in content-side JS state
|
|
41
40
|
// and is gone, but the native-host-side controller is still running).
|
|
42
41
|
const activeRunByProject = new Map();
|
|
43
|
-
const pendingPlans = new Map();
|
|
44
|
-
const PENDING_PLAN_TTL_MS = 30 * 60 * 1000;
|
|
45
42
|
const CODEX_RUN_PASSTHROUGH_ERROR_CODES = new Set(['thread_resume_failed', 'codex_no_usable_result']);
|
|
46
43
|
|
|
47
44
|
async function handleRequest(request, env = process.env, emit = () => {}) {
|
|
@@ -136,7 +133,7 @@ async function handleRequest(request, env = process.env, emit = () => {}) {
|
|
|
136
133
|
}
|
|
137
134
|
|
|
138
135
|
if (request.method === 'task.confirm') {
|
|
139
|
-
return
|
|
136
|
+
return errorResponse(request.id, 'suggest_mode_removed', 'Suggest mode has been removed. Reload the extension and choose Ask or Auto.');
|
|
140
137
|
}
|
|
141
138
|
|
|
142
139
|
return errorResponse(request.id, 'method_not_found', `Unknown method: ${request.method}`);
|
|
@@ -716,8 +713,11 @@ async function handleTaskRun(request, env, emit) {
|
|
|
716
713
|
const params = request.params || {};
|
|
717
714
|
const mode = params.mode;
|
|
718
715
|
|
|
719
|
-
if (
|
|
720
|
-
return errorResponse(request.id, '
|
|
716
|
+
if (mode === 'confirm') {
|
|
717
|
+
return errorResponse(request.id, 'suggest_mode_removed', 'Suggest mode has been removed. Choose Ask or Auto.');
|
|
718
|
+
}
|
|
719
|
+
if (!['ask', 'auto'].includes(mode)) {
|
|
720
|
+
return errorResponse(request.id, 'invalid_mode', 'Mode must be "ask" or "auto"');
|
|
721
721
|
}
|
|
722
722
|
|
|
723
723
|
if (mode === 'auto' && !params.checkpoint?.ok && !isVerifiedReviewing(params.reviewing)) {
|
|
@@ -805,24 +805,6 @@ function isVerifiedReviewing(reviewing) {
|
|
|
805
805
|
return reviewing?.ok === true && reviewing.status !== 'manual-override';
|
|
806
806
|
}
|
|
807
807
|
|
|
808
|
-
async function handleTaskConfirm(request) {
|
|
809
|
-
const planId = request.params?.planId;
|
|
810
|
-
purgeExpiredPendingPlans();
|
|
811
|
-
if (!planId || !pendingPlans.has(planId)) {
|
|
812
|
-
return errorResponse(request.id, 'plan_not_found', 'No pending task plan matched the supplied planId');
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
const plan = pendingPlans.get(planId);
|
|
816
|
-
pendingPlans.delete(planId);
|
|
817
|
-
|
|
818
|
-
return okResponse(request.id, {
|
|
819
|
-
status: 'confirmed',
|
|
820
|
-
notes: plan.notes || '',
|
|
821
|
-
userReport: plan.userReport,
|
|
822
|
-
operations: plan.operations
|
|
823
|
-
});
|
|
824
|
-
}
|
|
825
|
-
|
|
826
808
|
function buildDefaultTaskResult(mode, operations, params = {}) {
|
|
827
809
|
if (mode === 'ask') {
|
|
828
810
|
return {
|
|
@@ -836,16 +818,6 @@ function buildDefaultTaskResult(mode, operations, params = {}) {
|
|
|
836
818
|
|
|
837
819
|
const summary = buildOperationSummary(operations);
|
|
838
820
|
|
|
839
|
-
if (mode === 'confirm') {
|
|
840
|
-
return {
|
|
841
|
-
status: 'requires_task_confirmation',
|
|
842
|
-
summary,
|
|
843
|
-
notes: '',
|
|
844
|
-
userReport: buildDefaultUserReport(mode, operations, params),
|
|
845
|
-
operations
|
|
846
|
-
};
|
|
847
|
-
}
|
|
848
|
-
|
|
849
821
|
const split = splitDeletePlan(operations);
|
|
850
822
|
if (split.needsConfirmation.length > 0) {
|
|
851
823
|
return {
|
|
@@ -889,7 +861,7 @@ function normalizeAgentResult(mode, result, params = {}) {
|
|
|
889
861
|
};
|
|
890
862
|
|
|
891
863
|
if (!normalized.status) {
|
|
892
|
-
normalized.status =
|
|
864
|
+
normalized.status = 'completed';
|
|
893
865
|
}
|
|
894
866
|
|
|
895
867
|
return normalized;
|
|
@@ -911,40 +883,7 @@ function prepareResultForResponse(mode, result) {
|
|
|
911
883
|
}
|
|
912
884
|
}
|
|
913
885
|
|
|
914
|
-
|
|
915
|
-
if (confirmOperations.length > 0) {
|
|
916
|
-
result = {
|
|
917
|
-
...result,
|
|
918
|
-
status: 'requires_task_confirmation',
|
|
919
|
-
summary: buildOperationSummary(confirmOperations),
|
|
920
|
-
operations: confirmOperations
|
|
921
|
-
};
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
if (mode !== 'confirm' || result.status !== 'requires_task_confirmation') {
|
|
925
|
-
return result;
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
purgeExpiredPendingPlans();
|
|
929
|
-
const planId = `plan_${crypto.randomUUID()}`;
|
|
930
|
-
pendingPlans.set(planId, {
|
|
931
|
-
createdAt: Date.now(),
|
|
932
|
-
expiresAt: Date.now() + PENDING_PLAN_TTL_MS,
|
|
933
|
-
notes: result.notes || '',
|
|
934
|
-
userReport: result.userReport,
|
|
935
|
-
operations: Array.isArray(result.operations) ? result.operations : []
|
|
936
|
-
});
|
|
937
|
-
|
|
938
|
-
const {
|
|
939
|
-
operations: _operations,
|
|
940
|
-
pendingOperations: _pendingOperations,
|
|
941
|
-
deletePlan: _deletePlan,
|
|
942
|
-
...redacted
|
|
943
|
-
} = result;
|
|
944
|
-
return {
|
|
945
|
-
...redacted,
|
|
946
|
-
planId
|
|
947
|
-
};
|
|
886
|
+
return result;
|
|
948
887
|
}
|
|
949
888
|
|
|
950
889
|
function validateTaskResultOperationQuotas(result = {}) {
|
|
@@ -965,7 +904,7 @@ function buildDefaultUserReport(mode, operations = [], params = {}) {
|
|
|
965
904
|
|
|
966
905
|
return {
|
|
967
906
|
conclusion: hasOperations
|
|
968
|
-
? reportText(locale, 'Codex prepared
|
|
907
|
+
? reportText(locale, 'Codex prepared changes for writeback.', 'Codex 已准备好写回修改。')
|
|
969
908
|
: reportText(locale, 'This task completed without writing Overleaf files.', '这轮任务已完成,没有写入 Overleaf 文件。'),
|
|
970
909
|
checked,
|
|
971
910
|
findings: [],
|
|
@@ -975,7 +914,7 @@ function buildDefaultUserReport(mode, operations = [], params = {}) {
|
|
|
975
914
|
? ''
|
|
976
915
|
: (mode === 'ask' ? reportText(locale, 'This run was Ask mode.', '这轮是只问不改。') : ''),
|
|
977
916
|
nextStep: hasOperations
|
|
978
|
-
? reportText(locale, 'Review
|
|
917
|
+
? reportText(locale, 'Review the written changes in Overleaf.', '请在 Overleaf 中检查写入的修改。')
|
|
979
918
|
: reportText(locale, 'Continue the conversation, or add more @context and run another check.', '可以继续追问,或加入更多 @context 后再检查。')
|
|
980
919
|
};
|
|
981
920
|
}
|
|
@@ -1193,14 +1132,6 @@ function runExternalAgent(agentSpec, params, emit = () => {}, options = {}) {
|
|
|
1193
1132
|
});
|
|
1194
1133
|
}
|
|
1195
1134
|
|
|
1196
|
-
function purgeExpiredPendingPlans(now = Date.now()) {
|
|
1197
|
-
for (const [planId, plan] of pendingPlans.entries()) {
|
|
1198
|
-
if (Number.isFinite(plan?.expiresAt) && plan.expiresAt <= now) {
|
|
1199
|
-
pendingPlans.delete(planId);
|
|
1200
|
-
}
|
|
1201
|
-
}
|
|
1202
|
-
}
|
|
1203
|
-
|
|
1204
1135
|
function parsePositiveInteger(value, fallback) {
|
|
1205
1136
|
const parsed = Number.parseInt(value, 10);
|
|
1206
1137
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
@@ -1295,6 +1226,5 @@ module.exports = {
|
|
|
1295
1226
|
buildDefaultTaskResult,
|
|
1296
1227
|
getActiveNativeWorkState,
|
|
1297
1228
|
handleRequest,
|
|
1298
|
-
parseAgentEventLines
|
|
1299
|
-
purgeExpiredPendingPlans
|
|
1229
|
+
parseAgentEventLines
|
|
1300
1230
|
};
|
|
@@ -743,6 +743,8 @@ function cleanupOrphanStageRoots(updatesRoot, retainedRoots = []) {
|
|
|
743
743
|
|
|
744
744
|
function recoverAndReadStatus(context) {
|
|
745
745
|
let journal = readJournal(context);
|
|
746
|
+
const alignedVersion = readAlignedManagedVersion(context);
|
|
747
|
+
journal = supersedeObsoleteJournal(context, journal, alignedVersion);
|
|
746
748
|
if (journal?.state === 'activation_pending') {
|
|
747
749
|
journal = { ...journal, state: 'staged', reasonCode: 'update_activation_interrupted', updatedAt: new Date().toISOString() };
|
|
748
750
|
writeJournal(context, journal);
|
|
@@ -753,7 +755,7 @@ function recoverAndReadStatus(context) {
|
|
|
753
755
|
writeJournal(context, journal);
|
|
754
756
|
settleAuthorization(context, journal.authorizationId, 'revoked');
|
|
755
757
|
}
|
|
756
|
-
if (journal?.state === 'rolled_back') {
|
|
758
|
+
if (journal?.state === 'rolled_back' || journal?.state === 'superseded') {
|
|
757
759
|
pruneNativeVersions(context.nativeRoot, new Set([
|
|
758
760
|
readVersionPointer(context.nativeRoot, 'active-version'),
|
|
759
761
|
readVersionPointer(context.nativeRoot, 'previous-version')
|
|
@@ -768,6 +770,36 @@ function recoverAndReadStatus(context) {
|
|
|
768
770
|
};
|
|
769
771
|
}
|
|
770
772
|
|
|
773
|
+
function readAlignedManagedVersion(context) {
|
|
774
|
+
try {
|
|
775
|
+
return assertManagedLayout(context);
|
|
776
|
+
} catch (_error) {
|
|
777
|
+
return '';
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
function supersedeObsoleteJournal(context, journal, activeVersion) {
|
|
782
|
+
if (!journal || journal.state === 'superseded' || !parseSemver(activeVersion) ||
|
|
783
|
+
!parseSemver(journal.sourceVersion) || !parseSemver(journal.targetVersion) ||
|
|
784
|
+
compareSemver(activeVersion, journal.sourceVersion) <= 0 ||
|
|
785
|
+
compareSemver(activeVersion, journal.targetVersion) <= 0) {
|
|
786
|
+
return journal;
|
|
787
|
+
}
|
|
788
|
+
const timestamp = new Date().toISOString();
|
|
789
|
+
const superseded = {
|
|
790
|
+
...journal,
|
|
791
|
+
state: 'superseded',
|
|
792
|
+
supersededFromState: journal.state,
|
|
793
|
+
supersededByVersion: activeVersion,
|
|
794
|
+
supersededAt: timestamp,
|
|
795
|
+
updatedAt: timestamp
|
|
796
|
+
};
|
|
797
|
+
writeJournal(context, superseded);
|
|
798
|
+
cleanupStage(journal.stageRoot);
|
|
799
|
+
cleanupOrphanStageRoots(context.updatesRoot);
|
|
800
|
+
return superseded;
|
|
801
|
+
}
|
|
802
|
+
|
|
771
803
|
function pruneNativeVersions(nativeRoot, retainedVersions) {
|
|
772
804
|
const versionsRoot = path.join(nativeRoot, 'versions');
|
|
773
805
|
let entries = [];
|
|
@@ -960,6 +992,9 @@ function publicTransaction(journal) {
|
|
|
960
992
|
appliedAt: journal.appliedAt,
|
|
961
993
|
confirmedAt: journal.confirmedAt,
|
|
962
994
|
rolledBackAt: journal.rolledBackAt,
|
|
995
|
+
supersededAt: journal.supersededAt,
|
|
996
|
+
supersededByVersion: journal.supersededByVersion,
|
|
997
|
+
supersededFromState: journal.supersededFromState,
|
|
963
998
|
reasonCode: journal.reasonCode || ''
|
|
964
999
|
};
|
|
965
1000
|
}
|