codex-overleaf-link 2.5.0 → 2.6.0
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 +155 -392
- package/README.zh-CN.md +154 -393
- package/extension/bootstrap/background.js +52 -9
- package/extension/bootstrap/manifest.template.json +1 -1
- package/extension/bootstrap/popup.html +1 -0
- package/extension/bootstrap/popupFallback.js +55 -0
- package/extension/bootstrap/updateStatus.js +1 -0
- package/extension/src/background.js +283 -55
- package/extension/src/backgroundBootstrapMigration.js +181 -0
- package/extension/src/backgroundSharedSessions.js +129 -16
- package/extension/src/backgroundUpdateCoordinator.js +242 -29
- package/extension/src/backgroundUpdateSafety.js +173 -0
- package/extension/src/content/activeTurnControl.js +171 -8
- package/extension/src/content/applyResultFormatters.js +46 -73
- package/extension/src/content/assetTransferBroker.js +72 -14
- package/extension/src/content/composerAttachments.js +104 -47
- package/extension/src/content/composerPanel.js +110 -12
- package/extension/src/content/contentRuntime.js +1555 -926
- package/extension/src/content/contextTray.js +8 -2
- package/extension/src/content/contextUsageView.js +267 -0
- package/extension/src/content/diagnosticsController.js +122 -96
- package/extension/src/content/diagnosticsExport.js +19 -5
- package/extension/src/content/diagnosticsPanel.js +48 -0
- package/extension/src/content/directoryCleanupRecovery.js +54 -0
- package/extension/src/content/generated/content.bundle.js +11077 -3412
- package/extension/src/content/generated/content.bundle.meta.json +14 -3
- package/extension/src/content/globalPreferencesController.js +1 -1
- package/extension/src/content/legacyGlobalRegistry.js +10 -0
- package/extension/src/content/localSkillsPanel.js +104 -14
- package/extension/src/content/markdownDomRenderer.js +5 -3
- package/extension/src/content/markdownText.js +47 -11
- package/extension/src/content/modelPicker.js +8 -4
- package/extension/src/content/nativeCompatibilityController.js +74 -30
- package/extension/src/content/otWarmMirror.js +5 -6
- package/extension/src/content/otWarmMirrorController.js +17 -20
- package/extension/src/content/pageBridgeClient.js +17 -4
- package/extension/src/content/panelMaintenance.js +46 -14
- package/extension/src/content/panelRenderer.js +57 -27
- package/extension/src/content/pendingInputView.js +1 -1
- package/extension/src/content/projectProviderSelection.js +13 -4
- package/extension/src/content/projectSessionCleanup.js +109 -62
- package/extension/src/content/projectSettingsCoordinator.js +67 -6
- package/extension/src/content/providerSettingsCoordinator.js +46 -8
- package/extension/src/content/providerSettingsDialog.js +73 -14
- package/extension/src/content/recentProjects.js +15 -8
- package/extension/src/content/runActivitySummary.js +160 -18
- package/extension/src/content/runCompletionMeta.js +532 -0
- package/extension/src/content/runController.js +39 -15
- package/extension/src/content/runFailureNotice.js +29 -13
- package/extension/src/content/runGuidanceController.js +72 -27
- package/extension/src/content/runGuidanceView.js +59 -10
- package/extension/src/content/runPresence.js +18 -8
- package/extension/src/content/runQueueScheduler.js +157 -47
- package/extension/src/content/runRecoveryActions.js +147 -0
- package/extension/src/content/runResultActions.js +28 -143
- package/extension/src/content/runReviewController.js +633 -0
- package/extension/src/content/runScrollLayout.js +21 -2
- package/extension/src/content/runTimelineView.js +367 -175
- package/extension/src/content/scopedPersistencePanelState.js +134 -20
- package/extension/src/content/selectionContextView.js +1 -1
- package/extension/src/content/sensitivePreflight.js +153 -0
- package/extension/src/content/sessionForkController.js +80 -17
- package/extension/src/content/sessionManager.js +50 -4
- package/extension/src/content/sessionMenuView.js +54 -18
- package/extension/src/content/sessionPersistence.js +25 -5
- package/extension/src/content/settingsPanel.js +22 -5
- package/extension/src/content/settingsWorkbench.js +132 -89
- package/extension/src/content/sharedSessionViewSync.js +49 -11
- package/extension/src/content/subagentActivityView.js +23 -7
- package/extension/src/content/updateIdle.js +4 -1
- package/extension/src/content/updateNotice.js +118 -12
- package/extension/src/content/updateSafetyReceiver.js +58 -0
- package/extension/src/content/writebackController.js +53 -4
- package/extension/src/content/writebackOrchestrator.js +116 -94
- package/extension/src/content/writingStyleSettings.js +35 -11
- package/extension/src/page/binaryAssetUploader.js +136 -14
- package/extension/src/page/compileBridge.js +193 -180
- package/extension/src/page/fileMover.js +256 -0
- package/extension/src/page/overleafCapabilities.js +4 -1
- package/extension/src/page/ownedDirectoryCleanup.js +94 -0
- package/extension/src/page/referenceProjects.js +1 -0
- package/extension/src/page/reviewContext.js +113 -0
- package/extension/src/page/saveState.js +6 -4
- package/extension/src/page/snapshotRouter.js +84 -39
- package/extension/src/page/textCoordinates.js +17 -1
- package/extension/src/page/textFileCreator.js +114 -26
- package/extension/src/page/trackedChangeCapture.js +12 -2
- package/extension/src/page/trackedChangeOwnership.js +19 -1
- package/extension/src/page/trackedChangeReplay.js +41 -21
- package/extension/src/page/trackedChangesLifecycle.js +217 -199
- package/extension/src/page/treeOperations.js +7 -10
- package/extension/src/page/updateSafetyProbe.js +41 -0
- package/extension/src/page/writebackReceiptJournal.js +2 -0
- package/extension/src/page/writebackRouter.js +103 -155
- package/extension/src/pageBridge.js +126 -69
- package/extension/src/popup.js +62 -10
- package/extension/src/shared/agentTranscript.js +373 -17
- package/extension/src/shared/auditRecords.js +4 -0
- package/extension/src/shared/compatibility.js +22 -6
- package/extension/src/shared/compileAdapter.js +129 -66
- package/extension/src/shared/composerAttachmentDraft.js +156 -0
- package/extension/src/shared/contextUsage.js +125 -0
- package/extension/src/shared/directoryCleanupProof.js +43 -0
- package/extension/src/shared/failureReasons.js +349 -4
- package/extension/src/shared/globalPreferences.js +30 -13
- package/extension/src/shared/governanceRules.js +4 -37
- package/extension/src/shared/i18n.js +590 -24
- package/extension/src/shared/lineReferences.js +38 -31
- package/extension/src/shared/managedUpdateProjection.js +2 -2
- package/extension/src/shared/nativeRequestIdentity.js +1 -0
- package/extension/src/shared/pageRpcContract.js +5 -4
- package/extension/src/shared/panelIcons.js +39 -0
- package/extension/src/shared/projectFiles.js +21 -44
- package/extension/src/shared/providerProfiles.js +5 -3
- package/extension/src/shared/reviewing.js +130 -1
- package/extension/src/shared/runActivityModel.js +70 -4
- package/extension/src/shared/runExecutionSnapshot.js +13 -0
- package/extension/src/shared/runInputQueue.js +48 -5
- package/extension/src/shared/selectionContext.js +12 -3
- package/extension/src/shared/sessionState.js +132 -28
- package/extension/src/shared/sessionTitle.js +14 -1
- package/extension/src/shared/settlementFacts.js +10 -2
- package/extension/src/shared/sharedSessionBridge.js +118 -27
- package/extension/src/shared/sharedSessionTransfer.js +140 -0
- package/extension/src/shared/staleGuard.js +166 -52
- package/extension/src/shared/storageDb.js +90 -26
- package/extension/src/shared/storageMigration.js +78 -112
- package/extension/src/shared/storageRunActions.js +267 -30
- package/extension/src/shared/subagentActivityModel.js +1 -1
- package/extension/src/shared/undoOperations.js +253 -32
- package/extension/src/shared/updateConsent.js +6 -4
- package/extension/src/shared/updateRuntimeIdentity.js +17 -3
- package/extension/src/shared/writebackIntent.js +16 -0
- package/extension/src/shared/writebackOperationEvidence.js +4 -15
- package/extension/src/shared/writebackSettlement.js +58 -40
- package/extension/styles/panel.css +1123 -493
- package/native-host/src/anthropicBridgeRequest.js +4 -2
- package/native-host/src/anthropicBridgeResponse.js +6 -2
- package/native-host/src/anthropicMessagesBridge.js +24 -16
- package/native-host/src/bootstrapMigration.js +296 -0
- package/native-host/src/bootstrapMigrationContract.js +101 -0
- package/native-host/src/bootstrapUpdate.js +269 -0
- package/native-host/src/bootstrapUpdateWatchdog.js +44 -0
- package/native-host/src/chatBridgeRequest.js +60 -6
- package/native-host/src/chatBridgeResponse.js +20 -1
- package/native-host/src/chatCompletionsBridge.js +48 -15
- package/native-host/src/codexConfigPaths.js +106 -0
- package/native-host/src/codexHome.js +66 -73
- package/native-host/src/codexHomeScope.js +124 -0
- package/native-host/src/codexInheritedAuth.js +90 -0
- package/native-host/src/codexLocalSkills.js +301 -0
- package/native-host/src/codexPromptAssembly.js +114 -127
- package/native-host/src/codexProviderTest.js +24 -26
- package/native-host/src/codexSessionRunner.js +234 -198
- package/native-host/src/codexSessionTiming.js +18 -8
- package/native-host/src/codexSkillIsolation.js +170 -0
- package/native-host/src/codexThreadFork.js +19 -3
- package/native-host/src/index.js +19 -7
- package/native-host/src/managedInstall.js +110 -35
- package/native-host/src/managedInstallRecovery.js +140 -0
- package/native-host/src/managedRuntimeEvidence.js +57 -0
- package/native-host/src/mirrorWorkspace.js +92 -22
- package/native-host/src/nativeDoctor.js +15 -0
- package/native-host/src/nativeHelperLifecycle.js +21 -0
- package/native-host/src/nativeHostRegistration.js +33 -0
- package/native-host/src/nativeRunLifecycle.js +71 -0
- package/native-host/src/processStopBarrier.js +42 -7
- package/native-host/src/projectPathPlatform.js +30 -0
- package/native-host/src/providerContextError.js +20 -0
- package/native-host/src/providerHttp.js +80 -0
- package/native-host/src/providerProfile.js +4 -2
- package/native-host/src/providerReasoning.js +2 -7
- package/native-host/src/providerRuntime.js +1 -0
- package/native-host/src/providerStore.js +72 -14
- package/native-host/src/responsesPassthroughBridge.js +266 -52
- package/native-host/src/runtimeInstaller.js +21 -1
- package/native-host/src/selectionScope.js +36 -8
- package/native-host/src/subagentAdmission.js +26 -0
- package/native-host/src/subagentBroker.js +79 -66
- package/native-host/src/subagentTelemetry.js +19 -10
- package/native-host/src/subagentWorkspacePath.js +5 -2
- package/native-host/src/taskRunnerRuntime.js +92 -57
- package/native-host/src/textPatch.js +473 -377
- package/native-host/src/tomlStatements.js +140 -0
- package/native-host/src/updateManager.js +409 -46
- package/native-host/src/writingStyleRuntime.js +57 -29
- package/native-host/src/writingStyleStore.js +73 -0
- package/package.json +5 -8
- package/scripts/install-managed.mjs +1 -0
|
@@ -132,6 +132,18 @@
|
|
|
132
132
|
};
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
+
// Commit the explicit preflight decision to both live and durable run consumers.
|
|
136
|
+
// The originally captured (possibly queued) snapshot stays immutable.
|
|
137
|
+
function applyUntrackedDecision(view, record, choice) {
|
|
138
|
+
if (!['continue', 'disable'].includes(choice) || !view?.recordId || record?.id !== view.recordId) {
|
|
139
|
+
throw Codec.snapshotError('invalid_reviewing_decision', 'An explicit decision for the current run is required.');
|
|
140
|
+
}
|
|
141
|
+
const snapshot = create({ ...snapshotOf(view), requireReviewing: false });
|
|
142
|
+
view.executionSnapshot = cloneSnapshot(snapshot);
|
|
143
|
+
Object.assign(record, toRunCompatibilityTuple(snapshot));
|
|
144
|
+
return snapshot;
|
|
145
|
+
}
|
|
146
|
+
|
|
135
147
|
function projectForDisplay(value = {}) {
|
|
136
148
|
const snapshot = snapshotOf(value);
|
|
137
149
|
return {
|
|
@@ -174,6 +186,7 @@
|
|
|
174
186
|
SCHEMA_VERSION: Codec.SCHEMA_VERSION,
|
|
175
187
|
TUPLE_FIELDS: Codec.TUPLE_FIELDS,
|
|
176
188
|
applyToState,
|
|
189
|
+
applyUntrackedDecision,
|
|
177
190
|
capture,
|
|
178
191
|
captureRawQueueTuple,
|
|
179
192
|
cloneSnapshot,
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
const MAX_TEXT_CHARS = 12000;
|
|
12
12
|
const MAX_QUEUE_BYTES = 128 * 1024;
|
|
13
13
|
const MAX_PERSISTED_QUEUE_BYTES = 512 * 1024;
|
|
14
|
+
const MAX_CUSTOM_INSTRUCTIONS_CHARS = 12000;
|
|
14
15
|
const ACTIVE_STATUSES = new Set(['claimed', 'executing', 'steering']);
|
|
15
16
|
const VALID_STATUSES = new Set(['queued', 'paused', ...ACTIVE_STATUSES]);
|
|
16
17
|
|
|
@@ -41,7 +42,7 @@
|
|
|
41
42
|
claimToken: status === 'claimed' || status === 'executing' ? String(raw.claimToken || '') : '',
|
|
42
43
|
pauseReason: status === 'paused' ? String(raw.pauseReason || '') : '',
|
|
43
44
|
executionSnapshot: RunExecutionSnapshot.cloneSnapshot(executionSnapshot),
|
|
44
|
-
payload:
|
|
45
|
+
payload: buildPayload(executionSnapshot, raw.payload?.submissionContext)
|
|
45
46
|
});
|
|
46
47
|
if (normalized.length >= MAX_ITEMS) {
|
|
47
48
|
break;
|
|
@@ -79,7 +80,7 @@
|
|
|
79
80
|
claimToken: '',
|
|
80
81
|
pauseReason: input.status === 'paused' ? String(input.pauseReason || '') : '',
|
|
81
82
|
executionSnapshot: RunExecutionSnapshot.cloneSnapshot(executionSnapshot),
|
|
82
|
-
payload:
|
|
83
|
+
payload: buildPayload(executionSnapshot, input.payload?.submissionContext)
|
|
83
84
|
};
|
|
84
85
|
const next = [...queue, item];
|
|
85
86
|
if (estimateLegacyBytes(next) > MAX_QUEUE_BYTES || estimateBytes(next) > MAX_PERSISTED_QUEUE_BYTES) {
|
|
@@ -137,7 +138,7 @@
|
|
|
137
138
|
item = {
|
|
138
139
|
...item,
|
|
139
140
|
executionSnapshot: RunExecutionSnapshot.cloneSnapshot(snapshot),
|
|
140
|
-
payload:
|
|
141
|
+
payload: buildPayload(snapshot, item.payload?.submissionContext)
|
|
141
142
|
};
|
|
142
143
|
} catch (error) {
|
|
143
144
|
return {
|
|
@@ -199,6 +200,46 @@
|
|
|
199
200
|
);
|
|
200
201
|
}
|
|
201
202
|
|
|
203
|
+
// Queue inputs persist only these submitted extras. Attachments stay unsupported,
|
|
204
|
+
// and older items must not acquire a later draft's one-turn context on promotion.
|
|
205
|
+
function normalizeSubmissionContext(value = {}, helpers = {}) {
|
|
206
|
+
const input = value && typeof value === 'object' ? value : {};
|
|
207
|
+
const normalizeText = (value, maxChars) => {
|
|
208
|
+
const text = typeof value === 'string' ? value : '';
|
|
209
|
+
return String(helpers.normalizeDisplay ? helpers.normalizeDisplay(text, maxChars) : text).slice(0, maxChars);
|
|
210
|
+
};
|
|
211
|
+
const safeId = value => typeof value === 'string'
|
|
212
|
+
&& /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,79}$/.test(value) && !value.includes('..')
|
|
213
|
+
&& !['__proto__', 'prototype', 'constructor'].includes(value);
|
|
214
|
+
const rawSkill = input.skillInvocation;
|
|
215
|
+
const installer = rawSkill?.id === 'skill-installer' && (rawSkill.scope == null || rawSkill.scope === 'builtin');
|
|
216
|
+
const skillInvocation = safeId(rawSkill?.id)
|
|
217
|
+
&& (installer || ['codex-overleaf', 'codex-local'].includes(rawSkill.scope))
|
|
218
|
+
? { id: rawSkill.id, title: normalizeText(rawSkill.title || rawSkill.id, 80),
|
|
219
|
+
...(installer ? {} : { scope: rawSkill.scope }) }
|
|
220
|
+
: null;
|
|
221
|
+
return {
|
|
222
|
+
customInstructions: normalizeText(input.customInstructions, MAX_CUSTOM_INSTRUCTIONS_CHARS),
|
|
223
|
+
skillLoadingSettings: {
|
|
224
|
+
loadCodexLocalSkills: input.skillLoadingSettings?.loadCodexLocalSkills === true,
|
|
225
|
+
loadCodexOverleafSkills: input.skillLoadingSettings?.loadCodexOverleafSkills === true
|
|
226
|
+
},
|
|
227
|
+
skillInvocation,
|
|
228
|
+
...(Array.isArray(input.enabledCodexLocalSkillIds) ? {
|
|
229
|
+
enabledCodexLocalSkillIds: [...new Set(input.enabledCodexLocalSkillIds.filter(safeId))]
|
|
230
|
+
} : {}),
|
|
231
|
+
enabledCodexOverleafSkillIds: [...new Set((Array.isArray(input.enabledCodexOverleafSkillIds)
|
|
232
|
+
? input.enabledCodexOverleafSkillIds : []).filter(safeId))]
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function buildPayload(snapshot, submissionContext, helpers) {
|
|
237
|
+
const payload = RunExecutionSnapshot.toQueuePayload(snapshot);
|
|
238
|
+
// Keep legacy absence compact; safe defaults are applied only at execution.
|
|
239
|
+
if (submissionContext == null) return payload;
|
|
240
|
+
return { ...payload, submissionContext: normalizeSubmissionContext(submissionContext, helpers) };
|
|
241
|
+
}
|
|
242
|
+
|
|
202
243
|
function normalizeTimestamp(value) {
|
|
203
244
|
return typeof value === 'string' && value ? value : new Date().toISOString();
|
|
204
245
|
}
|
|
@@ -237,7 +278,8 @@
|
|
|
237
278
|
speedTier: item.payload.speedTier,
|
|
238
279
|
autoRecompile: item.payload.autoRecompile,
|
|
239
280
|
requireReviewing: item.payload.requireReviewing,
|
|
240
|
-
focusFiles: item.payload.focusFiles
|
|
281
|
+
focusFiles: item.payload.focusFiles,
|
|
282
|
+
submissionContext: item.payload.submissionContext
|
|
241
283
|
}
|
|
242
284
|
: {}
|
|
243
285
|
};
|
|
@@ -269,7 +311,7 @@
|
|
|
269
311
|
claimToken: normalizeField(item?.claimToken, 160),
|
|
270
312
|
pauseReason: normalizeField(item?.pauseReason, 160),
|
|
271
313
|
executionSnapshot: compactSnapshot,
|
|
272
|
-
payload:
|
|
314
|
+
payload: buildPayload(compactSnapshot, payload.submissionContext, { normalizeDisplay })
|
|
273
315
|
};
|
|
274
316
|
})
|
|
275
317
|
.filter(item => item.id && item.text);
|
|
@@ -292,6 +334,7 @@
|
|
|
292
334
|
markExecuting,
|
|
293
335
|
markSteering,
|
|
294
336
|
normalizeQueue,
|
|
337
|
+
normalizeSubmissionContext,
|
|
295
338
|
pauseAll,
|
|
296
339
|
remove,
|
|
297
340
|
resumeAll,
|
|
@@ -6,20 +6,29 @@
|
|
|
6
6
|
const MAX_TEXT = 20000;
|
|
7
7
|
function normalize(value) {
|
|
8
8
|
if (!value || typeof value !== 'object') return null;
|
|
9
|
-
const path = typeof value.path === 'string' ? value.path
|
|
10
|
-
if (!path || path.
|
|
9
|
+
const path = typeof value.path === 'string' ? value.path : '';
|
|
10
|
+
if (!path || path.length > 2048 || path.trim() !== path || path.includes('\\')
|
|
11
|
+
|| /[\u0000-\u001f\u007f]/.test(path) || path.startsWith('/') || /^[A-Za-z]:/.test(path)
|
|
11
12
|
|| path.split('/').some(part => !part || part === '.' || part === '..')) return null;
|
|
12
13
|
if (typeof value.projectId !== 'string' || !value.projectId
|
|
13
14
|
|| typeof value.text !== 'string' || !value.text.length || value.text.length > MAX_TEXT
|
|
15
|
+
|| /[\uD800-\uDFFF]/u.test(value.text)
|
|
14
16
|
|| !Number.isSafeInteger(value.from) || !Number.isSafeInteger(value.to)
|
|
15
17
|
|| value.from < 0 || value.to <= value.from || value.to - value.from !== value.text.length
|
|
16
18
|
|| !/^[a-f0-9]{64}$/i.test(value.documentHash || '')) return null;
|
|
19
|
+
const proof = value.rebaseEvidence;
|
|
20
|
+
const rebaseEvidence = proof?.v === 1 && Number.isSafeInteger(proof.documentLength)
|
|
21
|
+
&& proof.documentLength >= value.to && /^[a-f0-9]{64}$/i.test(proof.prefixHash || '')
|
|
22
|
+
&& /^[a-f0-9]{64}$/i.test(proof.suffixHash || '')
|
|
23
|
+
? Object.freeze({ v: 1, documentLength: proof.documentLength,
|
|
24
|
+
prefixHash: proof.prefixHash.toLowerCase(), suffixHash: proof.suffixHash.toLowerCase() }) : null;
|
|
17
25
|
return Object.freeze({
|
|
18
|
-
projectId: value.projectId.slice(0, 160), path
|
|
26
|
+
projectId: value.projectId.slice(0, 160), path,
|
|
19
27
|
from: value.from, to: value.to, text: value.text,
|
|
20
28
|
lineStart: Number.isSafeInteger(value.lineStart) && value.lineStart > 0 ? value.lineStart : 1,
|
|
21
29
|
lineEnd: Number.isSafeInteger(value.lineEnd) && value.lineEnd > 0 ? value.lineEnd : 1,
|
|
22
30
|
documentHash: value.documentHash.toLowerCase(),
|
|
31
|
+
...(rebaseEvidence ? { rebaseEvidence } : {}),
|
|
23
32
|
mode: value.mode === 'edit' ? 'edit' : 'reference',
|
|
24
33
|
capturedAt: typeof value.capturedAt === 'string' ? value.capturedAt.slice(0, 64) : ''
|
|
25
34
|
});
|
|
@@ -10,12 +10,15 @@
|
|
|
10
10
|
require('./sessionTitle'),
|
|
11
11
|
require('./runActivityModel'),
|
|
12
12
|
require('./subagentActivityModel'),
|
|
13
|
-
require('./writebackIntent')
|
|
13
|
+
require('./writebackIntent'),
|
|
14
|
+
require('./directoryCleanupProof'),
|
|
15
|
+
require('./undoOperations'),
|
|
16
|
+
require('./contextUsage')
|
|
14
17
|
);
|
|
15
18
|
} else {
|
|
16
19
|
root.CodexOverleafModuleRegistry.define(
|
|
17
20
|
'SessionState',
|
|
18
|
-
['I18n', 'SettlementFacts', 'RunInputQueue', 'SelectionContext', 'LineReferences', 'PathRedaction', 'SessionTitle', 'RunActivityModel', 'SubagentActivityModel', 'WritebackIntent'],
|
|
21
|
+
['I18n', 'SettlementFacts', 'RunInputQueue', 'SelectionContext', 'LineReferences', 'PathRedaction', 'SessionTitle', 'RunActivityModel', 'SubagentActivityModel', 'WritebackIntent', 'DirectoryCleanupProof', 'UndoOperations', 'ContextUsage'],
|
|
19
22
|
factory
|
|
20
23
|
);
|
|
21
24
|
}
|
|
@@ -29,7 +32,10 @@
|
|
|
29
32
|
SessionTitle,
|
|
30
33
|
RunActivityModel,
|
|
31
34
|
SubagentActivityModel,
|
|
32
|
-
WritebackIntent
|
|
35
|
+
WritebackIntent,
|
|
36
|
+
DirectoryCleanupProof,
|
|
37
|
+
UndoOperations,
|
|
38
|
+
ContextUsage
|
|
33
39
|
) {
|
|
34
40
|
'use strict';
|
|
35
41
|
|
|
@@ -46,6 +52,7 @@
|
|
|
46
52
|
loadCodexLocalSkills: true,
|
|
47
53
|
loadCodexOverleafSkills: true,
|
|
48
54
|
codexOverleafSkillEnabled: {},
|
|
55
|
+
codexLocalSkillEnabled: {},
|
|
49
56
|
theme: 'dark',
|
|
50
57
|
panelWidth: 380,
|
|
51
58
|
task: '',
|
|
@@ -120,7 +127,6 @@
|
|
|
120
127
|
statusTextChars: 400,
|
|
121
128
|
attachmentPreviewChars: 160 * 1024
|
|
122
129
|
};
|
|
123
|
-
const REDACTED_SECRET = '[REDACTED_SECRET]';
|
|
124
130
|
const SECRET_REDACTION_PATTERNS = [
|
|
125
131
|
/-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z0-9 ]*PRIVATE KEY-----/g,
|
|
126
132
|
/\bBearer\s+[A-Za-z0-9._~+/=-]{12,}/gi,
|
|
@@ -153,6 +159,7 @@
|
|
|
153
159
|
state.loadCodexLocalSkills = state.loadCodexLocalSkills !== false;
|
|
154
160
|
state.loadCodexOverleafSkills = state.loadCodexOverleafSkills !== false;
|
|
155
161
|
state.codexOverleafSkillEnabled = normalizeCodexOverleafSkillEnabled(state.codexOverleafSkillEnabled);
|
|
162
|
+
state.codexLocalSkillEnabled = normalizeCodexLocalSkillEnabled(state.codexLocalSkillEnabled);
|
|
156
163
|
state.theme = ['dark', 'light', 'auto'].includes(state.theme) ? state.theme : 'dark';
|
|
157
164
|
state.panelWidth = normalizePanelWidth(state.panelWidth);
|
|
158
165
|
state.task = typeof state.task === 'string' ? state.task : '';
|
|
@@ -213,6 +220,8 @@
|
|
|
213
220
|
const history = normalizeHistoryEntries(session.history);
|
|
214
221
|
const normalizedRuns = normalizeRuns(session.runs, options);
|
|
215
222
|
const runs = normalizedRuns.length ? normalizedRuns : recoverRunsFromHistory(session, history);
|
|
223
|
+
for (const run of runs) pruneRunRecoveryScope(run, session);
|
|
224
|
+
|
|
216
225
|
const rawTitle = typeof session.title === 'string' ? session.title.trim() : '';
|
|
217
226
|
const derivedTitle = deriveSessionTitle(runs, session.task);
|
|
218
227
|
const titleSource = normalizeTitleSource(session.titleSource, rawTitle, derivedTitle);
|
|
@@ -243,6 +252,7 @@
|
|
|
243
252
|
selectionContext: SelectionContext.normalize(session.selectionContext),
|
|
244
253
|
projectReferenceFiles: normalizeProjectReferenceFiles(session.projectReferenceFiles),
|
|
245
254
|
codexThreadId: typeof session.codexThreadId === 'string' ? session.codexThreadId : '',
|
|
255
|
+
contextUsage: ContextUsage.normalize(session.contextUsage),
|
|
246
256
|
forkedFromSessionId: typeof session.forkedFromSessionId === 'string' ? session.forkedFromSessionId : '',
|
|
247
257
|
forkedFromRunId: typeof session.forkedFromRunId === 'string' ? session.forkedFromRunId : '',
|
|
248
258
|
pendingInputs: normalizePendingInputs(
|
|
@@ -323,6 +333,7 @@
|
|
|
323
333
|
focusFiles: normalizeFocusFiles(active.focusFiles),
|
|
324
334
|
projectReferenceFiles: normalizeProjectReferenceFiles(active.projectReferenceFiles),
|
|
325
335
|
codexThreadId: active.codexThreadId || '',
|
|
336
|
+
contextUsage: ContextUsage.normalize(active.contextUsage),
|
|
326
337
|
providerId: state.providerId || 'builtin'
|
|
327
338
|
};
|
|
328
339
|
state.runs = Array.isArray(active.runs) ? active.runs : [];
|
|
@@ -367,6 +378,7 @@
|
|
|
367
378
|
selectionContext: SelectionContext.normalize(overrides.selectionContext),
|
|
368
379
|
projectReferenceFiles: normalizeProjectReferenceFiles(overrides.projectReferenceFiles),
|
|
369
380
|
codexThreadId: typeof overrides.codexThreadId === 'string' ? overrides.codexThreadId : '',
|
|
381
|
+
contextUsage: ContextUsage.normalize(overrides.contextUsage),
|
|
370
382
|
forkedFromSessionId: typeof overrides.forkedFromSessionId === 'string' ? overrides.forkedFromSessionId : '',
|
|
371
383
|
forkedFromRunId: typeof overrides.forkedFromRunId === 'string' ? overrides.forkedFromRunId : '',
|
|
372
384
|
pendingInputs: normalizePendingInputs(overrides.pendingInputs)
|
|
@@ -432,6 +444,34 @@
|
|
|
432
444
|
});
|
|
433
445
|
}
|
|
434
446
|
|
|
447
|
+
// Composer input changes only the draft on an already normalized state.
|
|
448
|
+
// Keep live run/event objects intact so typing cannot detach their writers.
|
|
449
|
+
function updateActiveSessionDraft(state, task) {
|
|
450
|
+
const active = getActiveSession(state);
|
|
451
|
+
if (!active) {
|
|
452
|
+
return mirrorActiveSession({ ...state });
|
|
453
|
+
}
|
|
454
|
+
const draft = sanitizeAssistantVisibleText(task);
|
|
455
|
+
if (draft === active.task && draft === state.task) {
|
|
456
|
+
return state;
|
|
457
|
+
}
|
|
458
|
+
const rawTitle = typeof active.title === 'string' ? active.title.trim() : '';
|
|
459
|
+
const derivedTitle = deriveSessionTitle(active.runs, task);
|
|
460
|
+
const titleSource = normalizeTitleSource(active.titleSource, rawTitle, derivedTitle);
|
|
461
|
+
const next = {
|
|
462
|
+
...active,
|
|
463
|
+
task: draft,
|
|
464
|
+
updatedAt: new Date().toISOString(),
|
|
465
|
+
title: normalizeSessionTitle(rawTitle, derivedTitle, titleSource),
|
|
466
|
+
titleSource
|
|
467
|
+
};
|
|
468
|
+
return {
|
|
469
|
+
...state,
|
|
470
|
+
sessions: state.sessions.map(session => session === active ? next : session),
|
|
471
|
+
task: next.task
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
|
|
435
475
|
function setActiveSession(state, sessionId) {
|
|
436
476
|
if (!(state.sessions || []).some(session => session.id === sessionId)) {
|
|
437
477
|
return mirrorActiveSession(state);
|
|
@@ -642,7 +682,33 @@
|
|
|
642
682
|
finishedAt: Number.isFinite(Date.parse(run.finishedAt)) ? run.finishedAt : event.timestamp };
|
|
643
683
|
}
|
|
644
684
|
|
|
685
|
+
function pruneRunRecoveryScope(run, session = {}) {
|
|
686
|
+
const wrongAccount = proof => Object.prototype.hasOwnProperty.call(session, 'accountScopeId')
|
|
687
|
+
&& proof.accountScopeId !== session.accountScopeId;
|
|
688
|
+
const wrongProject = value => Boolean(session.projectId && value !== session.projectId);
|
|
689
|
+
if (run.pendingDirectoryCleanup && (run.pendingDirectoryCleanup.sessionId !== session.id
|
|
690
|
+
|| wrongAccount(run.pendingDirectoryCleanup) || wrongProject(run.pendingDirectoryCleanup.projectId))) delete run.pendingDirectoryCleanup;
|
|
691
|
+
applyTrackedChangeStatus(run, run.trackedChangeStatus);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
function normalizeRecoveryRetention(value) {
|
|
695
|
+
if (value?.state !== 'omitted') return undefined;
|
|
696
|
+
return { state: 'omitted', reason: ['run-budget', 'session-budget', 'fallback', 'invalid'].includes(value.reason)
|
|
697
|
+
? value.reason : 'invalid', bytes: Number.isSafeInteger(value.bytes) && value.bytes >= 0 ? value.bytes : 0,
|
|
698
|
+
...(value.directoryCleanup === true ? { directoryCleanup: true, ...(value.coreRetained === true ? { coreRetained: true } : {}) } : {}) };
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
// Normalization makes UI copies of the same record. This identity is page-local:
|
|
702
|
+
// it never travels through JSON/storage and is never shared by a replacement run.
|
|
703
|
+
const runIdentities = new WeakMap();
|
|
704
|
+
function sameRunIdentity(left, right) {
|
|
705
|
+
return Boolean(left && right && (left === right
|
|
706
|
+
|| (runIdentities.has(left) && runIdentities.get(left) === runIdentities.get(right))));
|
|
707
|
+
}
|
|
708
|
+
|
|
645
709
|
function normalizeRun(run, options = {}) {
|
|
710
|
+
const sourceRun = run;
|
|
711
|
+
|
|
646
712
|
if (options.restoreRunningRuns === true || options.recoverSettledRuns === true) run = recoverSettledRunningRun(run);
|
|
647
713
|
run = recoverRecordedRunFailure(run, options.locale);
|
|
648
714
|
const shouldStopRestoredRun = options.restoreRunningRuns === true && run.status === 'running';
|
|
@@ -658,6 +724,12 @@
|
|
|
658
724
|
status: 'failed',
|
|
659
725
|
kind: 'report',
|
|
660
726
|
detail: i18n.t(locale, 'restoredRunStoppedDetail'),
|
|
727
|
+
detailStructured: {
|
|
728
|
+
conclusion: i18n.t(locale, 'restoredRunStoppedDetail'),
|
|
729
|
+
conclusionSource: { origin: 'product', key: 'reload_interrupted' },
|
|
730
|
+
// Ask forbids writeback; an interrupted Auto run has no zero-write proof.
|
|
731
|
+
meta: run.mode === 'ask' ? [{ key: 'writeResult', value: 'wrote 0 items, skipped 0 items' }] : []
|
|
732
|
+
},
|
|
661
733
|
failure: { code: 'native_request_failed', source: 'panel_reload' },
|
|
662
734
|
timestamp: new Date().toISOString()
|
|
663
735
|
});
|
|
@@ -687,9 +759,14 @@
|
|
|
687
759
|
undoBaseFiles: normalizeRunFiles(run.undoBaseFiles),
|
|
688
760
|
undoTrackedChanges: normalizeRunTrackedChanges(run.undoTrackedChanges),
|
|
689
761
|
undoExpectedFiles: normalizeRunFiles(run.undoExpectedFiles),
|
|
762
|
+
...(normalizeRecoveryRetention(run.recoveryRetention) && !run.forkSnapshot
|
|
763
|
+
? { recoveryRetention: normalizeRecoveryRetention(run.recoveryRetention) } : {}),
|
|
690
764
|
undoStatus: sanitizeAssistantVisibleText(run.undoStatus),
|
|
765
|
+
...(run.undoOwnerProtocol === 1 ? { undoOwnerProtocol: 1 } : {}),
|
|
691
766
|
nativeRequestId: sanitizeAssistantVisibleText(run.nativeRequestId),
|
|
767
|
+
...(run.operation === 'compact' ? { operation: 'compact' } : {}),
|
|
692
768
|
codexThreadId: sanitizeAssistantVisibleText(run.codexThreadId), codexTurnId: sanitizeAssistantVisibleText(run.codexTurnId),
|
|
769
|
+
contextUsage: run.forkSnapshot === true ? null : ContextUsage.normalize(run.contextUsage),
|
|
693
770
|
forkSnapshot: run.forkSnapshot === true,
|
|
694
771
|
forkSourceRunId: sanitizeAssistantVisibleText(run.forkSourceRunId),
|
|
695
772
|
nativeEventSeq: Number.isFinite(Number(run.nativeEventSeq)) ? Number(run.nativeEventSeq) : 0,
|
|
@@ -712,9 +789,15 @@
|
|
|
712
789
|
if (Array.isArray(run.trackedChangeCaptures) && run.trackedChangeCaptures.length && !run.forkSnapshot) {
|
|
713
790
|
normalized.trackedChangeCaptures = sanitizeAssistantVisibleValue(run.trackedChangeCaptures);
|
|
714
791
|
}
|
|
792
|
+
const directories = DirectoryCleanupProof.normalize(run.pendingDirectoryCleanup);
|
|
793
|
+
if (directories && directories.runId === normalized.id && directories.projectId === normalized.runProjectId
|
|
794
|
+
&& !run.forkSnapshot) normalized.pendingDirectoryCleanup = directories;
|
|
715
795
|
applyTrackedChangeStatus(normalized, run.trackedChangeStatus);
|
|
716
796
|
Object.assign(normalized, pickWritebackRecovery(run));
|
|
717
797
|
|
|
798
|
+
const identity = runIdentities.get(sourceRun) || {};
|
|
799
|
+
runIdentities.set(sourceRun, identity);
|
|
800
|
+
runIdentities.set(normalized, identity);
|
|
718
801
|
return normalized;
|
|
719
802
|
}
|
|
720
803
|
|
|
@@ -724,6 +807,7 @@
|
|
|
724
807
|
// output yields the same result.
|
|
725
808
|
function applyTrackedChangeStatus(run, rawStatus) {
|
|
726
809
|
const hasRefs = run.undoTrackedChanges.length > 0;
|
|
810
|
+
const hasFileUndo = (run.undoOperations || []).some(UndoOperations.isFileUndoOperation);
|
|
727
811
|
const hasRawStatus = rawStatus !== undefined && rawStatus !== null && rawStatus !== '';
|
|
728
812
|
|
|
729
813
|
// Step 1 — value recovery. Keep a stable value; recover any other present
|
|
@@ -740,12 +824,11 @@
|
|
|
740
824
|
}
|
|
741
825
|
|
|
742
826
|
// Step 1 — reload reconciliation. A non-terminal status (`pending`) with no
|
|
743
|
-
// refs
|
|
744
|
-
//
|
|
745
|
-
// the run returns to the legacy-undo world. A terminal status with no refs
|
|
827
|
+
// refs can result from an old record or a storage-budget omission. Drop
|
|
828
|
+
// pending and let actual legacy Undo material decide the action. A terminal status with no refs
|
|
746
829
|
// is kept — step 3 already empties terminal payloads and the label stays
|
|
747
830
|
// meaningful.
|
|
748
|
-
if (!hasRefs && status === 'pending') {
|
|
831
|
+
if (!hasRefs && !hasFileUndo && status === 'pending') {
|
|
749
832
|
status = undefined;
|
|
750
833
|
}
|
|
751
834
|
|
|
@@ -762,7 +845,7 @@
|
|
|
762
845
|
|
|
763
846
|
if (status !== undefined) {
|
|
764
847
|
run.trackedChangeStatus = status;
|
|
765
|
-
}
|
|
848
|
+
} else delete run.trackedChangeStatus;
|
|
766
849
|
}
|
|
767
850
|
|
|
768
851
|
// Welcome-panel + write-guard: the run lifecycle now
|
|
@@ -1034,6 +1117,17 @@
|
|
|
1034
1117
|
return result;
|
|
1035
1118
|
}
|
|
1036
1119
|
|
|
1120
|
+
function normalizeCodexLocalSkillEnabled(value) {
|
|
1121
|
+
const result = {};
|
|
1122
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return result;
|
|
1123
|
+
for (const [id, enabled] of Object.entries(value)) {
|
|
1124
|
+
if (/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,79}$/.test(id) && !id.includes('..')
|
|
1125
|
+
&& !['__proto__', 'prototype', 'constructor'].includes(id) && typeof enabled === 'boolean') result[id] = enabled;
|
|
1126
|
+
}
|
|
1127
|
+
if (Object.keys(result).length > 200) throw new Error('Too many skill preferences.');
|
|
1128
|
+
return result;
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1037
1131
|
function normalizeProjectPrefKey(value) {
|
|
1038
1132
|
const key = typeof value === 'string' ? value.trim() : '';
|
|
1039
1133
|
if (!key) {
|
|
@@ -1105,6 +1199,7 @@
|
|
|
1105
1199
|
loadCodexLocalSkills: source.loadCodexLocalSkills !== false,
|
|
1106
1200
|
loadCodexOverleafSkills: source.loadCodexOverleafSkills !== false,
|
|
1107
1201
|
codexOverleafSkillEnabled: normalizeCodexOverleafSkillEnabled(source.codexOverleafSkillEnabled),
|
|
1202
|
+
codexLocalSkillEnabled: normalizeCodexLocalSkillEnabled(source.codexLocalSkillEnabled),
|
|
1108
1203
|
theme: ['dark', 'light', 'auto'].includes(source.theme) ? source.theme : 'dark',
|
|
1109
1204
|
panelWidth: normalizePanelWidth(source.panelWidth),
|
|
1110
1205
|
task: summarizeTextForStorage(active?.task || source.task || '', 'task'),
|
|
@@ -1190,6 +1285,7 @@
|
|
|
1190
1285
|
selectionContext: SelectionContext.normalize(session.selectionContext),
|
|
1191
1286
|
projectReferenceFiles: normalizeProjectReferenceFiles(session.projectReferenceFiles),
|
|
1192
1287
|
codexThreadId: typeof session.codexThreadId === 'string' ? session.codexThreadId : '',
|
|
1288
|
+
contextUsage: ContextUsage.normalize(session.contextUsage),
|
|
1193
1289
|
forkedFromSessionId: normalizeTextField(session.forkedFromSessionId, 160),
|
|
1194
1290
|
forkedFromRunId: normalizeTextField(session.forkedFromRunId, 160),
|
|
1195
1291
|
pendingInputs: normalizePendingInputs(session.pendingInputs)
|
|
@@ -1278,19 +1374,32 @@
|
|
|
1278
1374
|
events: compactRunEvents(run.events, limits),
|
|
1279
1375
|
...(run.subagents?.length ? { subagents: SubagentActivityModel.normalize(run.subagents, sanitizeAssistantVisibleText) } : {}),
|
|
1280
1376
|
attachments: compactRunAttachmentsForStorage(run.attachments, limits),
|
|
1281
|
-
appliedOperations:
|
|
1377
|
+
appliedOperations: UndoOperations.compactUnavailableUndoOperations(run),
|
|
1282
1378
|
undoOperations: undoPayload.undoOperations,
|
|
1283
1379
|
undoBaseFiles: undoPayload.undoBaseFiles,
|
|
1284
1380
|
undoTrackedChanges: undoPayload.undoTrackedChanges,
|
|
1285
1381
|
undoExpectedFiles: undoPayload.undoExpectedFiles,
|
|
1382
|
+
...(!run.forkSnapshot && (run.pendingDirectoryCleanup || run.recoveryRetention?.directoryCleanup === true || (run.undoStatus !== 'applied' && !['accepted', 'rejected'].includes(run.trackedChangeStatus)))
|
|
1383
|
+
&& (run.pendingDirectoryCleanup || run.recoveryRetention?.state === 'omitted' || ['appliedOperations', 'undoOperations', 'undoTrackedChanges', 'undoExpectedFiles']
|
|
1384
|
+
.some(key => Array.isArray(run[key]) && run[key].length))
|
|
1385
|
+
? { recoveryRetention: normalizeRecoveryRetention(run.recoveryRetention)
|
|
1386
|
+
|| { state: 'omitted', reason: 'fallback', bytes: 0, ...(run.pendingDirectoryCleanup ? { directoryCleanup: true } : {}) } } : {}),
|
|
1286
1387
|
undoStatus: summarizeTextForStorage(run.undoStatus, 'undo status'),
|
|
1388
|
+
...(run.undoOwnerProtocol === 1 ? { undoOwnerProtocol: 1 } : {}),
|
|
1287
1389
|
nativeRequestId: normalizeTextField(run.nativeRequestId, 160),
|
|
1390
|
+
...(run.operation === 'compact' ? { operation: 'compact' } : {}),
|
|
1288
1391
|
codexThreadId: normalizeTextField(run.codexThreadId, 160), codexTurnId: normalizeTextField(run.codexTurnId, 160),
|
|
1392
|
+
contextUsage: run.forkSnapshot === true ? null : ContextUsage.normalize(run.contextUsage),
|
|
1289
1393
|
forkSnapshot: run.forkSnapshot === true,
|
|
1290
1394
|
forkSourceRunId: normalizeTextField(run.forkSourceRunId, 160),
|
|
1291
1395
|
nativeEventSeq: Number.isFinite(Number(run.nativeEventSeq)) ? Number(run.nativeEventSeq) : 0,
|
|
1292
1396
|
queueItemId: normalizeTextField(run.queueItemId, 160)
|
|
1293
1397
|
};
|
|
1398
|
+
if (compact.recoveryRetention?.coreRetained === true && run.undoStatus !== 'applied'
|
|
1399
|
+
&& !TERMINAL_TRACKED_CHANGE_STATUS.has(run.trackedChangeStatus)
|
|
1400
|
+
&& ['appliedOperations', 'undoOperations', 'undoTrackedChanges', 'undoExpectedFiles'].some(key => run[key]?.length)) {
|
|
1401
|
+
delete compact.recoveryRetention.coreRetained;
|
|
1402
|
+
}
|
|
1294
1403
|
if (run.executionSnapshot && typeof run.executionSnapshot === 'object') {
|
|
1295
1404
|
compact.executionSnapshot = sanitizeAssistantVisibleValue(run.executionSnapshot);
|
|
1296
1405
|
}
|
|
@@ -1577,21 +1686,22 @@
|
|
|
1577
1686
|
if (typeof value !== 'string' || !value) {
|
|
1578
1687
|
return '';
|
|
1579
1688
|
}
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1689
|
+
// Conversation text is user/model content, not a credential field. Keep
|
|
1690
|
+
// examples and quoted values intact; local-reference display rules remain.
|
|
1691
|
+
if (!mightContainLocalReferenceText(value)) {
|
|
1692
|
+
return value;
|
|
1583
1693
|
}
|
|
1584
1694
|
if (LineReferences?.sanitizeLocalReferences) {
|
|
1585
1695
|
try {
|
|
1586
|
-
return LineReferences.sanitizeLocalReferences(
|
|
1696
|
+
return LineReferences.sanitizeLocalReferences(value, {
|
|
1587
1697
|
projectFiles: [],
|
|
1588
1698
|
context: 'persist'
|
|
1589
1699
|
});
|
|
1590
1700
|
} catch (_error) {
|
|
1591
|
-
return fallbackSanitizeLocalReferences(
|
|
1701
|
+
return fallbackSanitizeLocalReferences(value);
|
|
1592
1702
|
}
|
|
1593
1703
|
}
|
|
1594
|
-
return fallbackSanitizeLocalReferences(
|
|
1704
|
+
return fallbackSanitizeLocalReferences(value);
|
|
1595
1705
|
}
|
|
1596
1706
|
|
|
1597
1707
|
function mightContainLocalReferenceText(value) {
|
|
@@ -1619,18 +1729,6 @@
|
|
|
1619
1729
|
});
|
|
1620
1730
|
}
|
|
1621
1731
|
|
|
1622
|
-
function redactSecretLikeText(value) {
|
|
1623
|
-
if (typeof value !== 'string') {
|
|
1624
|
-
return '';
|
|
1625
|
-
}
|
|
1626
|
-
let redacted = value;
|
|
1627
|
-
for (const pattern of SECRET_REDACTION_PATTERNS) {
|
|
1628
|
-
pattern.lastIndex = 0;
|
|
1629
|
-
redacted = redacted.replace(pattern, REDACTED_SECRET);
|
|
1630
|
-
}
|
|
1631
|
-
return redacted;
|
|
1632
|
-
}
|
|
1633
|
-
|
|
1634
1732
|
function containsSecretLikeText(value) {
|
|
1635
1733
|
if (typeof value === 'string') {
|
|
1636
1734
|
return SECRET_REDACTION_PATTERNS.some(pattern => {
|
|
@@ -1703,6 +1801,9 @@
|
|
|
1703
1801
|
}
|
|
1704
1802
|
|
|
1705
1803
|
return {
|
|
1804
|
+
sameRunIdentity,
|
|
1805
|
+
normalizeRecoveryRetention,
|
|
1806
|
+
pruneRunRecoveryScope,
|
|
1706
1807
|
pickWritebackRecovery,
|
|
1707
1808
|
DEFAULT_PANEL_STATE,
|
|
1708
1809
|
createSession,
|
|
@@ -1716,11 +1817,14 @@
|
|
|
1716
1817
|
selectVisibleSessionsForList,
|
|
1717
1818
|
setActiveSession,
|
|
1718
1819
|
updateActiveSession,
|
|
1820
|
+
updateActiveSessionDraft,
|
|
1719
1821
|
normalizeRuns,
|
|
1720
1822
|
normalizeRunStatus,
|
|
1721
1823
|
recoverRecordedRunFailure,
|
|
1722
1824
|
recoverSettledRunningRun,
|
|
1825
|
+
normalizeCodexLocalSkillEnabled,
|
|
1723
1826
|
normalizeProjectReferenceFiles,
|
|
1827
|
+
normalizeComposerAttachmentsForPersistence,
|
|
1724
1828
|
normalizeSelectionContext: SelectionContext.normalize,
|
|
1725
1829
|
prepareStateForStorage,
|
|
1726
1830
|
estimateJsonBytes,
|
|
@@ -25,6 +25,19 @@
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
function fromPrompt(value, { sanitize = text => text, maxChars = 24 } = {}) {
|
|
28
|
+
let title = projectPrompt(value, { sanitize, maxChars });
|
|
29
|
+
// Display titles pass through normalization again on unrelated callbacks.
|
|
30
|
+
// Finish removing nested formatting/prefixes now, before acknowledging a title.
|
|
31
|
+
// The bound guards against an input that never settles.
|
|
32
|
+
for (let pass = 0; pass < 8; pass += 1) {
|
|
33
|
+
const next = projectPrompt(title, { sanitize, maxChars });
|
|
34
|
+
if (next === title) return title;
|
|
35
|
+
title = next;
|
|
36
|
+
}
|
|
37
|
+
return title;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function projectPrompt(value, { sanitize, maxChars }) {
|
|
28
41
|
if (typeof value !== 'string' || !value.trim()) return '';
|
|
29
42
|
const source = String(sanitize(value.slice(0, INPUT_LIMIT)) || '');
|
|
30
43
|
let fence = null;
|
|
@@ -75,7 +88,7 @@
|
|
|
75
88
|
.replace(/\[(?:REDACTED_SECRET|local path(?::\d+)?)\]/gi, ' ')
|
|
76
89
|
.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, '')
|
|
77
90
|
.replace(/\s+/g, ' ').trim()
|
|
78
|
-
.replace(/^(?:\u8bf7(?:\u4f60)?\u5e2e\u6211|\u8bf7\u4f60|\u5e2e\u6211|\u9ebb\u70e6\u4f60(?:\u5e2e\u6211)?|\u9ebb\u70e6\u5e2e\u6211|please\s+)\s
|
|
91
|
+
.replace(/^(?:(?:\u8bf7(?:\u4f60)?\u5e2e\u6211|\u8bf7\u4f60|\u5e2e\u6211|\u9ebb\u70e6\u4f60(?:\u5e2e\u6211)?|\u9ebb\u70e6\u5e2e\u6211|please\s+)\s*)+/i, '');
|
|
79
92
|
}
|
|
80
93
|
|
|
81
94
|
function isScaffolding(value) {
|
|
@@ -157,6 +157,9 @@
|
|
|
157
157
|
canAccept,
|
|
158
158
|
canUndo,
|
|
159
159
|
canRetry: Boolean(primaryFailure?.retryable),
|
|
160
|
+
requiresWriteReview: Boolean(facts && (facts.documentEffect === 'possibly-changed'
|
|
161
|
+
|| facts.evidence?.settled === 'needs-review'
|
|
162
|
+
|| facts.failures.some(failure => DefaultFailureReasons.isUnconfirmedWriteFailure?.(failure)))),
|
|
160
163
|
terminalState: failureTerminalState || '',
|
|
161
164
|
actions: { accept: canAccept, undo: canUndo }
|
|
162
165
|
};
|
|
@@ -209,6 +212,10 @@
|
|
|
209
212
|
file: safePath(item.file),
|
|
210
213
|
operationType: text(item.operationType).slice(0, 80),
|
|
211
214
|
changedDocument: item.changedDocument === true,
|
|
215
|
+
...(item.mayHaveMutated === true ? { mayHaveMutated: true } : {}),
|
|
216
|
+
...(item.evidence?.originalCode === 'native_untracked_undo_pending_changes'
|
|
217
|
+
&& item.changedDocument !== true && item.mayHaveMutated !== true && item.evidence.writeStarted !== true
|
|
218
|
+
? { evidence: { originalCode: 'native_untracked_undo_pending_changes' } } : {}),
|
|
212
219
|
terminalState: normalizeTerminalState(item.terminalState)
|
|
213
220
|
}));
|
|
214
221
|
}
|
|
@@ -287,8 +294,9 @@
|
|
|
287
294
|
}
|
|
288
295
|
|
|
289
296
|
function selectPrimaryFailure(failures) {
|
|
290
|
-
|
|
291
|
-
|
|
297
|
+
const select = DefaultFailureReasons?.selectPrimaryWritebackFailure || DefaultFailureReasons?.selectPrimaryFailure;
|
|
298
|
+
return select instanceof Function
|
|
299
|
+
? select(failures)
|
|
292
300
|
: failures[0] || null;
|
|
293
301
|
}
|
|
294
302
|
|