codex-overleaf-link 2.5.0 → 2.5.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 +38 -26
- package/README.zh-CN.md +39 -27
- 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 +206 -53
- package/extension/src/backgroundBootstrapMigration.js +181 -0
- package/extension/src/backgroundSharedSessions.js +74 -14
- package/extension/src/backgroundUpdateCoordinator.js +118 -21
- package/extension/src/backgroundUpdateSafety.js +173 -0
- package/extension/src/content/activeTurnControl.js +8 -2
- package/extension/src/content/applyResultFormatters.js +46 -73
- package/extension/src/content/assetTransferBroker.js +72 -14
- package/extension/src/content/composerAttachments.js +93 -45
- package/extension/src/content/composerPanel.js +18 -0
- package/extension/src/content/contentRuntime.js +661 -676
- package/extension/src/content/diagnosticsController.js +122 -96
- package/extension/src/content/diagnosticsExport.js +19 -5
- package/extension/src/content/diagnosticsPanel.js +30 -0
- package/extension/src/content/directoryCleanupRecovery.js +54 -0
- package/extension/src/content/generated/content.bundle.js +6879 -2786
- package/extension/src/content/generated/content.bundle.meta.json +11 -3
- package/extension/src/content/globalPreferencesController.js +1 -1
- package/extension/src/content/legacyGlobalRegistry.js +6 -0
- package/extension/src/content/localSkillsPanel.js +102 -12
- package/extension/src/content/markdownText.js +5 -6
- package/extension/src/content/modelPicker.js +7 -4
- package/extension/src/content/nativeCompatibilityController.js +45 -20
- package/extension/src/content/otWarmMirror.js +4 -5
- package/extension/src/content/otWarmMirrorController.js +17 -20
- package/extension/src/content/pageBridgeClient.js +15 -2
- package/extension/src/content/panelMaintenance.js +40 -12
- package/extension/src/content/panelRenderer.js +6 -0
- package/extension/src/content/projectProviderSelection.js +13 -4
- package/extension/src/content/projectSessionCleanup.js +109 -62
- package/extension/src/content/projectSettingsCoordinator.js +39 -2
- package/extension/src/content/providerSettingsCoordinator.js +46 -8
- package/extension/src/content/providerSettingsDialog.js +71 -13
- package/extension/src/content/recentProjects.js +11 -5
- package/extension/src/content/runActivitySummary.js +40 -6
- package/extension/src/content/runCompletionMeta.js +344 -0
- package/extension/src/content/runController.js +37 -14
- package/extension/src/content/runFailureNotice.js +21 -12
- package/extension/src/content/runGuidanceController.js +72 -27
- package/extension/src/content/runGuidanceView.js +59 -10
- package/extension/src/content/runQueueScheduler.js +148 -42
- package/extension/src/content/runRecoveryActions.js +146 -0
- package/extension/src/content/runResultActions.js +8 -125
- package/extension/src/content/runReviewController.js +574 -0
- package/extension/src/content/runScrollLayout.js +21 -2
- package/extension/src/content/runTimelineView.js +146 -153
- package/extension/src/content/scopedPersistencePanelState.js +51 -6
- package/extension/src/content/selectionContextView.js +1 -1
- package/extension/src/content/sensitivePreflight.js +140 -0
- package/extension/src/content/sessionForkController.js +80 -17
- package/extension/src/content/sessionManager.js +1 -1
- package/extension/src/content/settingsPanel.js +7 -3
- package/extension/src/content/settingsWorkbench.js +5 -0
- package/extension/src/content/sharedSessionViewSync.js +45 -8
- package/extension/src/content/updateIdle.js +4 -1
- package/extension/src/content/updateNotice.js +60 -8
- package/extension/src/content/updateSafetyReceiver.js +58 -0
- package/extension/src/content/writebackController.js +53 -4
- package/extension/src/content/writebackOrchestrator.js +82 -73
- package/extension/src/content/writingStyleSettings.js +35 -11
- package/extension/src/page/binaryAssetUploader.js +136 -14
- package/extension/src/page/fileMover.js +256 -0
- 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/textFileCreator.js +105 -25
- 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 +80 -79
- package/extension/src/pageBridge.js +19 -3
- package/extension/src/popup.js +62 -10
- package/extension/src/shared/agentTranscript.js +23 -0
- package/extension/src/shared/auditRecords.js +2 -0
- package/extension/src/shared/compatibility.js +22 -6
- package/extension/src/shared/compileAdapter.js +79 -57
- package/extension/src/shared/composerAttachmentDraft.js +151 -0
- package/extension/src/shared/directoryCleanupProof.js +43 -0
- package/extension/src/shared/failureReasons.js +309 -3
- package/extension/src/shared/globalPreferences.js +30 -13
- package/extension/src/shared/governanceRules.js +4 -37
- package/extension/src/shared/i18n.js +298 -2
- 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/projectFiles.js +21 -44
- package/extension/src/shared/providerProfiles.js +5 -3
- package/extension/src/shared/runInputQueue.js +48 -5
- package/extension/src/shared/selectionContext.js +12 -3
- package/extension/src/shared/sessionState.js +72 -27
- package/extension/src/shared/settlementFacts.js +10 -2
- package/extension/src/shared/sharedSessionBridge.js +37 -14
- package/extension/src/shared/sharedSessionTransfer.js +140 -0
- package/extension/src/shared/staleGuard.js +118 -13
- package/extension/src/shared/storageDb.js +58 -26
- package/extension/src/shared/storageMigration.js +71 -111
- package/extension/src/shared/storageRunActions.js +209 -26
- package/extension/src/shared/subagentActivityModel.js +1 -1
- package/extension/src/shared/undoOperations.js +136 -13
- package/extension/src/shared/updateConsent.js +6 -4
- package/extension/src/shared/updateRuntimeIdentity.js +1 -1
- package/extension/src/shared/writebackIntent.js +16 -0
- package/extension/src/shared/writebackOperationEvidence.js +4 -15
- package/extension/src/shared/writebackSettlement.js +38 -38
- package/extension/styles/panel.css +19 -5
- 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 +233 -0
- package/native-host/src/bootstrapUpdateWatchdog.js +44 -0
- package/native-host/src/chatBridgeResponse.js +10 -0
- package/native-host/src/chatCompletionsBridge.js +21 -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 +31 -12
- package/native-host/src/codexProviderTest.js +24 -26
- package/native-host/src/codexSessionRunner.js +110 -183
- 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/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 +77 -54
- package/native-host/src/tomlStatements.js +140 -0
- package/native-host/src/updateManager.js +297 -39
- package/native-host/src/writingStyleRuntime.js +57 -29
- package/native-host/src/writingStyleStore.js +73 -0
- package/package.json +1 -1
- package/scripts/install-managed.mjs +1 -0
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"entry": "extension/entries/content-entry.mjs",
|
|
4
4
|
"output": "extension/src/content/generated/content.bundle.js",
|
|
5
|
-
"sourceDigest": "
|
|
6
|
-
"outputDigest": "
|
|
7
|
-
"byteLength":
|
|
5
|
+
"sourceDigest": "548acfc19dd7be907e0c5494f2da2e11fa68dfc501e0552846ad63d4e5a35dba",
|
|
6
|
+
"outputDigest": "404e0523fc534b56e87ea96e62cd112514c06ce034209ec7a05feef83d7a64a9",
|
|
7
|
+
"byteLength": 3162346,
|
|
8
8
|
"inputs": [
|
|
9
9
|
"extension/entries/content-entry.mjs",
|
|
10
10
|
"extension/src/content/activeTurnControl.js",
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"extension/src/content/diagnosticsExport.js",
|
|
20
20
|
"extension/src/content/diagnosticsPanel.js",
|
|
21
21
|
"extension/src/content/diffReviewPanel.js",
|
|
22
|
+
"extension/src/content/directoryCleanupRecovery.js",
|
|
22
23
|
"extension/src/content/globalPreferencesController.js",
|
|
23
24
|
"extension/src/content/legacyGlobalRegistry.js",
|
|
24
25
|
"extension/src/content/localSkillsPanel.js",
|
|
@@ -46,13 +47,16 @@
|
|
|
46
47
|
"extension/src/content/recentProjects.js",
|
|
47
48
|
"extension/src/content/reviewHunks.js",
|
|
48
49
|
"extension/src/content/runActivitySummary.js",
|
|
50
|
+
"extension/src/content/runCompletionMeta.js",
|
|
49
51
|
"extension/src/content/runController.js",
|
|
50
52
|
"extension/src/content/runFailureNotice.js",
|
|
51
53
|
"extension/src/content/runGuidanceController.js",
|
|
52
54
|
"extension/src/content/runGuidanceView.js",
|
|
53
55
|
"extension/src/content/runPresence.js",
|
|
54
56
|
"extension/src/content/runQueueScheduler.js",
|
|
57
|
+
"extension/src/content/runRecoveryActions.js",
|
|
55
58
|
"extension/src/content/runResultActions.js",
|
|
59
|
+
"extension/src/content/runReviewController.js",
|
|
56
60
|
"extension/src/content/runScrollLayout.js",
|
|
57
61
|
"extension/src/content/runSettlementPersistence.js",
|
|
58
62
|
"extension/src/content/runTimelineView.js",
|
|
@@ -60,6 +64,7 @@
|
|
|
60
64
|
"extension/src/content/scopedPersistenceDetachedCommit.js",
|
|
61
65
|
"extension/src/content/scopedPersistencePanelState.js",
|
|
62
66
|
"extension/src/content/selectionContextView.js",
|
|
67
|
+
"extension/src/content/sensitivePreflight.js",
|
|
63
68
|
"extension/src/content/sessionForkController.js",
|
|
64
69
|
"extension/src/content/sessionManager.js",
|
|
65
70
|
"extension/src/content/sessionMenuView.js",
|
|
@@ -83,6 +88,8 @@
|
|
|
83
88
|
"extension/src/shared/changeHistoryModel.js",
|
|
84
89
|
"extension/src/shared/compatibility.js",
|
|
85
90
|
"extension/src/shared/compileAdapter.js",
|
|
91
|
+
"extension/src/shared/composerAttachmentDraft.js",
|
|
92
|
+
"extension/src/shared/directoryCleanupProof.js",
|
|
86
93
|
"extension/src/shared/failureReasons.js",
|
|
87
94
|
"extension/src/shared/globalPreferences.js",
|
|
88
95
|
"extension/src/shared/governanceRules.js",
|
|
@@ -110,6 +117,7 @@
|
|
|
110
117
|
"extension/src/shared/sessionTitle.js",
|
|
111
118
|
"extension/src/shared/settlementFacts.js",
|
|
112
119
|
"extension/src/shared/sharedSessionBridge.js",
|
|
120
|
+
"extension/src/shared/sharedSessionTransfer.js",
|
|
113
121
|
"extension/src/shared/staleGuard.js",
|
|
114
122
|
"extension/src/shared/storageDb.js",
|
|
115
123
|
"extension/src/shared/storageKeys.js",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
if (force || changed.includes('theme')) options.applyTheme?.(values.theme);
|
|
41
41
|
if (changed.includes('locale')) options.applyLocale?.();
|
|
42
42
|
if (force || changed.includes('preloadProjectContext')) options.onPreloadChange?.(values.preloadProjectContext);
|
|
43
|
-
if (changed.some(key => key === 'codexOverleafSkillEnabled' || key.startsWith('loadCodex'))) options.onSkillsChange?.();
|
|
43
|
+
if (changed.some(key => key === 'codexOverleafSkillEnabled' || key === 'codexLocalSkillEnabled' || key.startsWith('loadCodex'))) options.onSkillsChange?.();
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
function accept(value) {
|
|
@@ -20,10 +20,12 @@
|
|
|
20
20
|
'SelectionContext',
|
|
21
21
|
'SelectionContextView',
|
|
22
22
|
'WritebackIntent',
|
|
23
|
+
'DirectoryCleanupProof',
|
|
23
24
|
'ChangeHistoryModel',
|
|
24
25
|
'ChangeHistoryView',
|
|
25
26
|
'Compatibility',
|
|
26
27
|
'ComposerAttachments',
|
|
28
|
+
'ComposerAttachmentDraft',
|
|
27
29
|
'ComposerPanel',
|
|
28
30
|
'ContentRuntime',
|
|
29
31
|
'ContextTray',
|
|
@@ -61,6 +63,7 @@
|
|
|
61
63
|
'RunPresence',
|
|
62
64
|
'RunActivityModel',
|
|
63
65
|
'RunController',
|
|
66
|
+
'RunReviewController',
|
|
64
67
|
'RunExecutionSnapshot',
|
|
65
68
|
'RunGuidanceController',
|
|
66
69
|
'RunInputQueue',
|
|
@@ -73,6 +76,7 @@
|
|
|
73
76
|
'ScopedPersistenceCoordinator',
|
|
74
77
|
'ScopedPersistenceTransaction',
|
|
75
78
|
'SensitiveScan',
|
|
79
|
+
'SensitivePreflight',
|
|
76
80
|
'SessionManager',
|
|
77
81
|
'SessionForkController',
|
|
78
82
|
'SessionPanel',
|
|
@@ -93,6 +97,7 @@
|
|
|
93
97
|
'UpdateIdle',
|
|
94
98
|
'UpdateNotice',
|
|
95
99
|
'WritebackController',
|
|
100
|
+
'DirectoryCleanupRecovery',
|
|
96
101
|
'WritebackIntent',
|
|
97
102
|
'WritebackOrchestrator',
|
|
98
103
|
'WritebackPlan',
|
|
@@ -111,6 +116,7 @@
|
|
|
111
116
|
'ProviderProfiles',
|
|
112
117
|
'ProviderSettingsDialog',
|
|
113
118
|
'RunGuidanceView',
|
|
119
|
+
'RunRecoveryActions',
|
|
114
120
|
'SessionMenuView'
|
|
115
121
|
]);
|
|
116
122
|
|
|
@@ -17,11 +17,17 @@
|
|
|
17
17
|
document: documentDep = null,
|
|
18
18
|
getPanel = () => null,
|
|
19
19
|
getState = () => null,
|
|
20
|
+
getScope = () => '',
|
|
20
21
|
setState = () => {},
|
|
21
22
|
saveState = null,
|
|
22
23
|
sendBackgroundNative = () => Promise.resolve({ ok: false }),
|
|
23
24
|
getSkillLoadingSettings = () => ({ loadCodexOverleafSkills: true }),
|
|
24
25
|
isCodexOverleafSkillEnabled = () => true,
|
|
26
|
+
isCodexLocalSkillEnabled = (id, skill) => skill?.enabled !== false,
|
|
27
|
+
setCodexLocalSkillEnabled = () => {},
|
|
28
|
+
getCodexLocalSkills = () => [],
|
|
29
|
+
getCodexLocalSkillWarnings = () => [],
|
|
30
|
+
refreshCodexLocalSkills = async () => [],
|
|
25
31
|
setCodexOverleafSkillEnabled = () => {},
|
|
26
32
|
setProjectSettingsStatus = () => {},
|
|
27
33
|
tr = (key) => key,
|
|
@@ -36,27 +42,51 @@
|
|
|
36
42
|
|| root.document
|
|
37
43
|
|| (typeof globalThis !== 'undefined' ? globalThis.document : null);
|
|
38
44
|
|
|
45
|
+
let localSkillsListError = false;
|
|
46
|
+
let refreshGeneration = 0;
|
|
39
47
|
async function refreshLocalSkills() {
|
|
48
|
+
const generation = ++refreshGeneration;
|
|
49
|
+
const scope = getScope();
|
|
50
|
+
const isCurrent = () => generation === refreshGeneration && scope === getScope();
|
|
51
|
+
localSkillsListError = false;
|
|
40
52
|
showSkillListLoading();
|
|
53
|
+
const localList = getPanel()?.querySelector('[data-codex-local-skill-list]');
|
|
54
|
+
if (localList) {
|
|
55
|
+
localList.textContent = '';
|
|
56
|
+
appendLocalSkillEmpty(localList, 'codexOverleafSkillsLoading');
|
|
57
|
+
}
|
|
58
|
+
const localRefresh = localList ? refreshCodexLocalSkills({ force: true }) : Promise.resolve([]);
|
|
59
|
+
const localOutcome = localRefresh.then(() => {
|
|
60
|
+
if (isCurrent()) renderCodexLocalSkillList();
|
|
61
|
+
return null;
|
|
62
|
+
}, error => {
|
|
63
|
+
if (isCurrent()) { localSkillsListError = true; renderCodexLocalSkillList(); }
|
|
64
|
+
return error;
|
|
65
|
+
});
|
|
41
66
|
try {
|
|
42
67
|
const codexOverleafResponse = await sendBackgroundNative({
|
|
43
68
|
method: 'skills.list',
|
|
44
69
|
params: { scope: 'codex-overleaf' }
|
|
45
70
|
});
|
|
46
71
|
if (!codexOverleafResponse?.ok) {
|
|
47
|
-
throw new Error(
|
|
72
|
+
throw new Error(tx('Could not load Codex Overleaf skills. Try again.', '无法加载 Codex Overleaf 技能,请重试。'));
|
|
48
73
|
}
|
|
49
74
|
const codexOverleafSkills = Array.isArray(codexOverleafResponse.result?.skills)
|
|
50
75
|
? codexOverleafResponse.result.skills
|
|
51
76
|
: [];
|
|
77
|
+
if (!isCurrent()) return;
|
|
52
78
|
const state = getState() || {};
|
|
53
79
|
setState({
|
|
54
80
|
...state,
|
|
55
81
|
codexOverleafSkills
|
|
56
82
|
});
|
|
57
83
|
setSlashCodexOverleafSkills(codexOverleafSkills);
|
|
84
|
+
const localError = await localOutcome;
|
|
85
|
+
if (!isCurrent()) return;
|
|
58
86
|
renderLocalSkillList();
|
|
87
|
+
if (localError) throw localError;
|
|
59
88
|
} catch (err) {
|
|
89
|
+
if (!isCurrent()) return;
|
|
60
90
|
renderLocalSkillList();
|
|
61
91
|
throw err;
|
|
62
92
|
}
|
|
@@ -71,6 +101,7 @@
|
|
|
71
101
|
const placeholder = document.createElement('div');
|
|
72
102
|
placeholder.className = 'codex-project-settings-empty';
|
|
73
103
|
placeholder.textContent = tr('codexOverleafSkillsLoading');
|
|
104
|
+
placeholder.dataset.i18n = 'codexOverleafSkillsLoading';
|
|
74
105
|
list.append(placeholder);
|
|
75
106
|
}
|
|
76
107
|
|
|
@@ -84,6 +115,7 @@
|
|
|
84
115
|
}
|
|
85
116
|
|
|
86
117
|
function renderLocalSkillList() {
|
|
118
|
+
renderCodexLocalSkillList();
|
|
87
119
|
const list = getPanel()?.querySelector('[data-local-skill-list]');
|
|
88
120
|
if (!list) {
|
|
89
121
|
return;
|
|
@@ -93,10 +125,10 @@
|
|
|
93
125
|
const codexOverleafEnabled = getSkillLoadingSettings().loadCodexOverleafSkills !== false;
|
|
94
126
|
list.textContent = '';
|
|
95
127
|
if (!codexOverleafEnabled) {
|
|
96
|
-
appendLocalSkillEmpty(list,
|
|
128
|
+
appendLocalSkillEmpty(list, 'codexOverleafSkillsDisabled');
|
|
97
129
|
}
|
|
98
130
|
if (!codexOverleafSkills.length) {
|
|
99
|
-
appendLocalSkillEmpty(list,
|
|
131
|
+
appendLocalSkillEmpty(list, 'codexOverleafSkillsEmpty');
|
|
100
132
|
return;
|
|
101
133
|
}
|
|
102
134
|
for (const skill of codexOverleafSkills) {
|
|
@@ -104,6 +136,31 @@
|
|
|
104
136
|
}
|
|
105
137
|
}
|
|
106
138
|
|
|
139
|
+
function renderCodexLocalSkillList() {
|
|
140
|
+
const list = getPanel()?.querySelector('[data-codex-local-skill-list]');
|
|
141
|
+
if (!list) return;
|
|
142
|
+
list.textContent = '';
|
|
143
|
+
const enabled = getSkillLoadingSettings().loadCodexLocalSkills !== false;
|
|
144
|
+
if (!enabled) appendLocalSkillEmpty(list, 'codexLocalSkillsDisabled');
|
|
145
|
+
const skills = getCodexLocalSkills();
|
|
146
|
+
if (localSkillsListError) { appendLocalSkillEmpty(list, 'codexLocalSkillsLoadFailed'); return; }
|
|
147
|
+
if (!Array.isArray(skills)) { appendLocalSkillEmpty(list, 'codexOverleafSkillsLoading'); return; }
|
|
148
|
+
if (!skills.length) appendLocalSkillEmpty(list, 'codexLocalSkillsEmpty');
|
|
149
|
+
const skippedCount = getCodexLocalSkillWarnings().reduce((sum, warning) => sum + (warning?.code === 'codex_local_skills_skipped' ? warning.count : 0), 0);
|
|
150
|
+
if (skippedCount > 0) {
|
|
151
|
+
const warning = document.createElement('div');
|
|
152
|
+
warning.className = 'codex-project-settings-empty';
|
|
153
|
+
warning._refreshLocale = () => { warning.textContent = tr('codexLocalSkillsSkipped', { count: skippedCount }); };
|
|
154
|
+
warning._refreshLocale();
|
|
155
|
+
list.append(warning);
|
|
156
|
+
}
|
|
157
|
+
for (const skill of skills) {
|
|
158
|
+
const title = String(skill.title || skill.name || skill.id).trim();
|
|
159
|
+
const duplicateTitle = skills.filter(other => String(other.title || other.name || other.id).trim() === title).length > 1;
|
|
160
|
+
renderCodexOverleafSkillRow(list, { ...skill, title, duplicateTitle, scope: 'codex-local', removable: false }, enabled);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
107
164
|
function createSkillMark(id) {
|
|
108
165
|
const mark = document.createElement('span');
|
|
109
166
|
mark.className = 'codex-local-skill-icon';
|
|
@@ -123,10 +180,11 @@
|
|
|
123
180
|
if (!id) {
|
|
124
181
|
return;
|
|
125
182
|
}
|
|
183
|
+
const local = skill.scope === 'codex-local';
|
|
126
184
|
const compact = Boolean(list.closest?.('.codex-settings-workbench'));
|
|
127
185
|
const row = document.createElement('div');
|
|
128
186
|
row.className = 'codex-local-skill-row';
|
|
129
|
-
row.dataset.scope = 'codex-overleaf';
|
|
187
|
+
row.dataset.scope = local ? 'codex-local' : 'codex-overleaf';
|
|
130
188
|
if (!masterEnabled) {
|
|
131
189
|
row.dataset.disabled = 'true';
|
|
132
190
|
}
|
|
@@ -148,7 +206,7 @@
|
|
|
148
206
|
'annotated-rewrite': tx('Guided editing for document revisions.', '用于文稿修订的编辑流程。'),
|
|
149
207
|
'parallel-subagents': tx('Split independent subtasks across multiple agents.', '将相互独立的子任务分配给多个 agent。')
|
|
150
208
|
};
|
|
151
|
-
const description = descriptions[id]
|
|
209
|
+
const description = (!local && descriptions[id])
|
|
152
210
|
|| (typeof skill.description === 'string' ? skill.description.replace(/\s+/g, ' ').trim() : '');
|
|
153
211
|
if (description) {
|
|
154
212
|
const help = document.createElement('span');
|
|
@@ -157,7 +215,17 @@
|
|
|
157
215
|
help.title = description;
|
|
158
216
|
copy.append(help);
|
|
159
217
|
}
|
|
160
|
-
|
|
218
|
+
const sourceText = () => (skill.sourceKind === 'system' ? tx('Codex built-in', 'Codex 内置')
|
|
219
|
+
: skill.sourceKind === 'plugin' && skill.sourceLabel ? String(skill.sourceLabel) : tx('Local Codex', 'Codex 本地'))
|
|
220
|
+
+ (skill.duplicateTitle ? ' · ' + (skill.sourceHint || id.slice(-8)) : '');
|
|
221
|
+
let sourceLabel = null;
|
|
222
|
+
if (local) {
|
|
223
|
+
sourceLabel = document.createElement('span');
|
|
224
|
+
sourceLabel.className = 'codex-local-skill-description';
|
|
225
|
+
sourceLabel.textContent = sourceText();
|
|
226
|
+
copy.append(sourceLabel);
|
|
227
|
+
}
|
|
228
|
+
if (compact) row.append(createSkillMark(local ? '' : id));
|
|
161
229
|
row.append(copy);
|
|
162
230
|
const controls = compact ? document.createElement('div') : row;
|
|
163
231
|
if (compact) controls.className = 'codex-local-skill-controls';
|
|
@@ -166,14 +234,25 @@
|
|
|
166
234
|
const toggle = document.createElement('input');
|
|
167
235
|
toggle.type = 'checkbox';
|
|
168
236
|
toggle.className = 'codex-switch';
|
|
169
|
-
toggle.checked = isCodexOverleafSkillEnabled(id);
|
|
170
|
-
|
|
237
|
+
toggle.checked = local ? isCodexLocalSkillEnabled(id, skill) : isCodexOverleafSkillEnabled(id);
|
|
238
|
+
const accessibleSkillName = (trimmedTitle || id)
|
|
239
|
+
+ (local && skill.duplicateTitle ? ': ' + (skill.sourceHint || id.slice(-8)) : '');
|
|
240
|
+
toggle.setAttribute('aria-label', accessibleSkillName + ': ' + tr('codexOverleafSkillEnableToggle'));
|
|
171
241
|
if (!masterEnabled) {
|
|
172
242
|
toggle.disabled = true;
|
|
173
243
|
}
|
|
174
244
|
toggle.addEventListener('change', event => {
|
|
175
|
-
|
|
245
|
+
if (local) setCodexLocalSkillEnabled(id, event.target.checked);
|
|
246
|
+
else setCodexOverleafSkillEnabled(id, event.target.checked);
|
|
176
247
|
});
|
|
248
|
+
row._refreshLocale = () => {
|
|
249
|
+
if (sourceLabel) sourceLabel.textContent = sourceText();
|
|
250
|
+
toggle.setAttribute('aria-label', accessibleSkillName + ': ' + tr('codexOverleafSkillEnableToggle'));
|
|
251
|
+
const label = !local && id === 'annotated-rewrite' ? tx('Guided editing for document revisions.', '用于文稿修订的编辑流程。')
|
|
252
|
+
: !local && id === 'parallel-subagents' ? tx('Split independent subtasks across multiple agents.', '将相互独立的子任务分配给多个 agent。') : '';
|
|
253
|
+
const help = copy.querySelector('.codex-local-skill-description');
|
|
254
|
+
if (label && help) { help.textContent = label; help.title = label; }
|
|
255
|
+
};
|
|
177
256
|
|
|
178
257
|
if (skill.removable !== false) {
|
|
179
258
|
// The Remove / Confirm / Cancel controls share an actions container so
|
|
@@ -198,6 +277,11 @@
|
|
|
198
277
|
cancelBtn.type = 'button';
|
|
199
278
|
cancelBtn.className = 'codex-set-btn';
|
|
200
279
|
cancelBtn.textContent = tr('localSkillRemoveCancel');
|
|
280
|
+
const refreshRow = row._refreshLocale;
|
|
281
|
+
row._refreshLocale = () => {
|
|
282
|
+
refreshRow(); removeBtn.textContent = tr('localSkillRemove'); cancelBtn.textContent = tr('localSkillRemoveCancel');
|
|
283
|
+
confirmBtn.textContent = tr(confirmBtn.disabled ? 'localSkillRemoving' : 'localSkillRemoveConfirm');
|
|
284
|
+
};
|
|
201
285
|
|
|
202
286
|
function enterConfirming() {
|
|
203
287
|
// Reset any previously confirming row back to its Remove button state.
|
|
@@ -274,10 +358,11 @@
|
|
|
274
358
|
}
|
|
275
359
|
}
|
|
276
360
|
|
|
277
|
-
function appendLocalSkillEmpty(list,
|
|
361
|
+
function appendLocalSkillEmpty(list, key) {
|
|
278
362
|
const empty = document.createElement('div');
|
|
279
363
|
empty.className = 'codex-project-settings-empty';
|
|
280
|
-
empty.textContent =
|
|
364
|
+
empty.textContent = tr(key);
|
|
365
|
+
empty.dataset.i18n = key;
|
|
281
366
|
list.append(empty);
|
|
282
367
|
}
|
|
283
368
|
|
|
@@ -293,7 +378,7 @@
|
|
|
293
378
|
throw new Error(response?.error?.message || 'native host did not remove Codex Overleaf skill');
|
|
294
379
|
}
|
|
295
380
|
const activeSkill = normalizeComposerSkillInvocation(getComposerSkillInvocation());
|
|
296
|
-
if (activeSkill?.scope === 'codex-overleaf' && activeSkill.
|
|
381
|
+
if (activeSkill?.scope === 'codex-overleaf' && activeSkill.id === id) {
|
|
297
382
|
clearComposerSkillInvocation();
|
|
298
383
|
}
|
|
299
384
|
setProjectSettingsStatus(tr('codexOverleafSkillRemoveDone'), 'completed');
|
|
@@ -304,6 +389,11 @@
|
|
|
304
389
|
|
|
305
390
|
return {
|
|
306
391
|
refreshLocalSkills,
|
|
392
|
+
refreshLocale: () => {
|
|
393
|
+
for (const selector of ['[data-local-skill-list]', '[data-codex-local-skill-list]']) {
|
|
394
|
+
for (const row of getPanel()?.querySelector(selector)?.children || []) row._refreshLocale?.();
|
|
395
|
+
}
|
|
396
|
+
},
|
|
307
397
|
renderLocalSkillList,
|
|
308
398
|
removeCodexOverleafSkill
|
|
309
399
|
};
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
(function initCodexOverleafMarkdownText() {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// out of contentRuntime.js (v1.4.5 structural-debt phase 1). The code below
|
|
7
|
-
// moved verbatim (original indentation kept); the four runtime collaborators
|
|
8
|
-
// are factory-injected so behavior is unchanged.
|
|
4
|
+
// Assistant-text rendering, sanitizers, and line-reference controls.
|
|
5
|
+
// Runtime collaborators are factory-injected.
|
|
9
6
|
function create(deps = {}) {
|
|
10
7
|
const {
|
|
11
8
|
LineReferences,
|
|
@@ -588,7 +585,9 @@
|
|
|
588
585
|
return;
|
|
589
586
|
}
|
|
590
587
|
renderingDiagnosticKeys.add(key);
|
|
591
|
-
|
|
588
|
+
try {
|
|
589
|
+
if (typeof deps.recordRenderingDiagnostic === 'function') deps.recordRenderingDiagnostic({ code, detail });
|
|
590
|
+
} catch (_error) { /* A diagnostic sink must not interrupt rendering. */ }
|
|
592
591
|
}
|
|
593
592
|
|
|
594
593
|
function appendMarkdownParagraphFlow(target, value) {
|
|
@@ -117,11 +117,12 @@
|
|
|
117
117
|
if (generation !== modelLoadGeneration) {
|
|
118
118
|
return { stale: true };
|
|
119
119
|
}
|
|
120
|
+
options.assertCurrent?.();
|
|
120
121
|
const responseProviderId = response?.result?.providerId || '';
|
|
121
122
|
if (selection?.providerId && responseProviderId && responseProviderId !== selection.providerId) {
|
|
122
123
|
return { stale: true };
|
|
123
124
|
}
|
|
124
|
-
if (selection?.providerId && selection.providerId !== 'builtin'
|
|
125
|
+
if (response?.ok && selection?.providerId && selection.providerId !== 'builtin'
|
|
125
126
|
&& Number(response?.result?.providerRevision) !== Number(selection.providerRevision)) {
|
|
126
127
|
return { stale: true };
|
|
127
128
|
}
|
|
@@ -170,6 +171,7 @@
|
|
|
170
171
|
if (generation !== modelLoadGeneration) {
|
|
171
172
|
return { stale: true };
|
|
172
173
|
}
|
|
174
|
+
options.assertCurrent?.();
|
|
173
175
|
applyUnavailableModelOptions(error);
|
|
174
176
|
return { stale: false, error };
|
|
175
177
|
}
|
|
@@ -251,7 +253,7 @@
|
|
|
251
253
|
}
|
|
252
254
|
const option = document.createElement('option');
|
|
253
255
|
option.value = id;
|
|
254
|
-
option.textContent = model.label;
|
|
256
|
+
option.textContent = model.unverified && model.label === `${id} (custom)` ? tx(`${id} (custom)`, `${id}(自定义)`) : model.label;
|
|
255
257
|
option.dataset.reasoningEfforts = normalizeReasoningEffortsForSelect(model.reasoningEfforts).join(',');
|
|
256
258
|
option.dataset.defaultReasoningEffort = model.defaultReasoningEffort || '';
|
|
257
259
|
option.dataset.reasoningPresentation = model.reasoningPresentation || '';
|
|
@@ -269,7 +271,7 @@
|
|
|
269
271
|
if (selectedId && !renderedSelected && options.allowUnknownSelected !== false) {
|
|
270
272
|
const option = document.createElement('option');
|
|
271
273
|
option.value = selectedId;
|
|
272
|
-
option.textContent = `${selectedId} (custom)
|
|
274
|
+
option.textContent = tx(`${selectedId} (custom)`, `${selectedId}(自定义)`);
|
|
273
275
|
option.dataset.reasoningEfforts = '';
|
|
274
276
|
option.dataset.defaultReasoningEffort = '';
|
|
275
277
|
option.dataset.reasoningPresentation = 'none';
|
|
@@ -370,7 +372,7 @@
|
|
|
370
372
|
for (const option of Array.from(reasoningSelect.options || [])) {
|
|
371
373
|
list.append(createModelConfigChoice({
|
|
372
374
|
value: option.value,
|
|
373
|
-
label:
|
|
375
|
+
label: formatReasoningEffortLabel(option.value, reasoningSelect.dataset.presentation),
|
|
374
376
|
datasetName: 'reasoningChoice'
|
|
375
377
|
}));
|
|
376
378
|
}
|
|
@@ -384,6 +386,7 @@
|
|
|
384
386
|
}
|
|
385
387
|
list.textContent = '';
|
|
386
388
|
for (const option of Array.from(modelSelect.options || [])) {
|
|
389
|
+
if (option.dataset.unverified === 'true' && [`${option.value} (custom)`, `${option.value}(自定义)`].includes(option.textContent)) option.textContent = tx(`${option.value} (custom)`, `${option.value}(自定义)`);
|
|
387
390
|
const choice = createModelConfigChoice({
|
|
388
391
|
value: option.value,
|
|
389
392
|
label: option.textContent || option.value,
|
|
@@ -12,27 +12,46 @@
|
|
|
12
12
|
const tx = options.tx;
|
|
13
13
|
const tr = options.tr;
|
|
14
14
|
|
|
15
|
+
let installIdentity = options.getExtensionCompatibilityMetadata?.()?.installIdentity || {};
|
|
16
|
+
function resolveInstallCommand(compatibility = {}) {
|
|
17
|
+
const metadata = options.getExtensionCompatibilityMetadata?.() || {};
|
|
18
|
+
installIdentity = { ...installIdentity, ...(metadata.installIdentity || {}), ...(compatibility.installIdentity || {}) };
|
|
19
|
+
if (installIdentity.managed) return Compatibility?.buildInstallCommand?.(
|
|
20
|
+
compatibility.recommendedVersion || Compatibility?.BUILD_TARGET_VERSION,
|
|
21
|
+
compatibility.native?.platform || compatibility.platform || installIdentity.platform,
|
|
22
|
+
metadata.extensionId, installIdentity
|
|
23
|
+
) || '';
|
|
24
|
+
return compatibility.updateCommand || compatibility.installCommand || options.installCommand || '';
|
|
25
|
+
}
|
|
26
|
+
|
|
15
27
|
function sendNative(payload) {
|
|
16
28
|
return dispatch(payload, 'sendNative');
|
|
17
29
|
}
|
|
18
30
|
|
|
19
|
-
function sendBackgroundNative(payload) {
|
|
20
|
-
return dispatch(payload, 'sendBackgroundNative');
|
|
31
|
+
function sendBackgroundNative(payload, context = {}) {
|
|
32
|
+
return dispatch(payload, 'sendBackgroundNative', context);
|
|
21
33
|
}
|
|
22
34
|
|
|
23
|
-
async function dispatch(payload, channelMethod) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
async function dispatch(payload, channelMethod, context = {}) {
|
|
36
|
+
let compatibilityGate;
|
|
37
|
+
try {
|
|
38
|
+
compatibilityGate = await ensureForMethod(payload?.method, context);
|
|
39
|
+
if (!compatibilityGate.ok) return compatibilityGate.response;
|
|
40
|
+
// Post-Undo cache bookkeeping must survive the ended run's cancellation.
|
|
41
|
+
if (gatedMethods.has(payload?.method) && payload.method !== 'mirror.invalidate') {
|
|
42
|
+
options.throwIfCancellationRequested?.();
|
|
43
|
+
}
|
|
44
|
+
context.assertCurrent?.();
|
|
45
|
+
} catch (error) {
|
|
46
|
+
if (context.assertCurrent && error && typeof error === 'object') error.requestDispatched = false;
|
|
47
|
+
throw error;
|
|
29
48
|
}
|
|
30
49
|
return nativeChannel[channelMethod](
|
|
31
50
|
attachEvidence(payload, compatibilityGate.compatibility)
|
|
32
51
|
);
|
|
33
52
|
}
|
|
34
53
|
|
|
35
|
-
async function ensureForMethod(method) {
|
|
54
|
+
async function ensureForMethod(method, { assertCurrent } = {}) {
|
|
36
55
|
const metadata = options.getExtensionCompatibilityMetadata?.() || {};
|
|
37
56
|
const params = Compatibility?.buildBridgePingParams
|
|
38
57
|
? Compatibility.buildBridgePingParams(metadata)
|
|
@@ -41,9 +60,12 @@
|
|
|
41
60
|
method: 'bridge.ping',
|
|
42
61
|
params
|
|
43
62
|
});
|
|
63
|
+
// A retired run must not publish even a compatibility failure into a successor.
|
|
64
|
+
assertCurrent?.();
|
|
44
65
|
const compatibility = Compatibility?.evaluateNativeCompatibility
|
|
45
66
|
? Compatibility.evaluateNativeCompatibility(response, metadata)
|
|
46
67
|
: options.fallbackNativeCompatibility(response);
|
|
68
|
+
const installCommand = resolveInstallCommand(compatibility);
|
|
47
69
|
const allowed = !gatedMethods.has(method) ||
|
|
48
70
|
(Compatibility?.isNativeMethodAllowed
|
|
49
71
|
? Compatibility.isNativeMethodAllowed(method, compatibility)
|
|
@@ -51,14 +73,14 @@
|
|
|
51
73
|
if (allowed) return { ok: true, compatibility };
|
|
52
74
|
|
|
53
75
|
const message = formatBlockedMessage(method, compatibility);
|
|
54
|
-
const installCommand = options.installCommand;
|
|
55
76
|
const error = {
|
|
56
77
|
code: 'native_update_required',
|
|
57
78
|
message,
|
|
58
79
|
status: compatibility.status || 'unknown_native',
|
|
59
80
|
classification: options.getNativeCompatibilityClassification(compatibility),
|
|
60
|
-
|
|
61
|
-
|
|
81
|
+
installIdentity,
|
|
82
|
+
installCommand,
|
|
83
|
+
updateCommand: installCommand,
|
|
62
84
|
currentNativeVersion: compatibility.currentNativeVersion
|
|
63
85
|
|| compatibility.nativeVersion
|
|
64
86
|
|| compatibility.native?.version
|
|
@@ -102,6 +124,7 @@
|
|
|
102
124
|
: {};
|
|
103
125
|
const response = await sendBackgroundNative({ method: 'bridge.ping', params });
|
|
104
126
|
const compatibility = Compatibility.evaluateNativeCompatibility(response, metadata);
|
|
127
|
+
resolveInstallCommand(compatibility);
|
|
105
128
|
const classification = options.getNativeCompatibilityClassification(compatibility);
|
|
106
129
|
if (classification === 'compatible') {
|
|
107
130
|
options.setBadge?.(renderer.headerEl, { type: 'none' });
|
|
@@ -158,9 +181,7 @@
|
|
|
158
181
|
|| compatibility.nativeVersion
|
|
159
182
|
|| native.version
|
|
160
183
|
|| tx('missing', '未安装');
|
|
161
|
-
const command = compatibility
|
|
162
|
-
|| compatibility.installCommand
|
|
163
|
-
|| options.installCommand;
|
|
184
|
+
const command = resolveInstallCommand(compatibility);
|
|
164
185
|
const releaseUrl = compatibility.releaseUrl || '';
|
|
165
186
|
const overlay = options.document.createElement('div');
|
|
166
187
|
overlay.className = 'codex-plugin-confirm';
|
|
@@ -193,10 +214,12 @@
|
|
|
193
214
|
`Extension v${extensionVersion} / Native v${nativeVersion}`,
|
|
194
215
|
`扩展 v${extensionVersion} / Native v${nativeVersion}`
|
|
195
216
|
),
|
|
196
|
-
|
|
197
|
-
'
|
|
198
|
-
|
|
199
|
-
|
|
217
|
+
!command && installIdentity.managed
|
|
218
|
+
? tx('Repair Managed using the original managed root, browser and extension ID with install-managed.',
|
|
219
|
+
'请使用原管理根目录、浏览器及扩展 ID,通过 install-managed 修复托管安装。')
|
|
220
|
+
: tx('Run the command below, reload the extension, then refresh Overleaf.', '运行下面的命令,重新加载扩展,然后刷新 Overleaf。')
|
|
221
|
+
+ (installIdentity.managed && (native.platform || installIdentity.platform) === 'win32'
|
|
222
|
+
? tx(' Use PowerShell.', ' 请使用 PowerShell。') : '')
|
|
200
223
|
].join('\n\n');
|
|
201
224
|
const commandCode = options.document.createElement('code');
|
|
202
225
|
commandCode.textContent = command;
|
|
@@ -221,7 +244,9 @@
|
|
|
221
244
|
copy.type = 'button';
|
|
222
245
|
copy.className = 'codex-plugin-confirm-confirm';
|
|
223
246
|
copy.textContent = tx('Copy command', '复制命令');
|
|
247
|
+
copy.disabled = !command;
|
|
224
248
|
copy.addEventListener('click', async () => {
|
|
249
|
+
if (!command) return;
|
|
225
250
|
await options.navigator.clipboard.writeText(command);
|
|
226
251
|
copy.textContent = tx('Copied', '已复制');
|
|
227
252
|
});
|
|
@@ -237,7 +262,7 @@
|
|
|
237
262
|
if (event.target === overlay) overlay.remove();
|
|
238
263
|
});
|
|
239
264
|
panel.append(overlay);
|
|
240
|
-
copy.focus();
|
|
265
|
+
(command ? copy : close).focus();
|
|
241
266
|
}
|
|
242
267
|
|
|
243
268
|
function scheduleFirstUseOnboardingTip() {
|
|
@@ -833,7 +833,7 @@
|
|
|
833
833
|
if (getCurrentProjectId() !== projectId) return { useExistingMirror: false, reason: 'project_changed' };
|
|
834
834
|
const otWarmStart = otWarmMirrorController.canUseOtWarmStart({
|
|
835
835
|
enabled: isExperimentalOtEnabled() && !otWarmMirrorState.failureActive,
|
|
836
|
-
focusFiles,
|
|
836
|
+
focusFiles, focusFilesAreLiteral: true,
|
|
837
837
|
mirrorStatus
|
|
838
838
|
});
|
|
839
839
|
if (!mirrorStatus?.exists || (!otWarmStart.ok && !isMirrorReusable(mirrorStatus))) {
|
|
@@ -858,10 +858,9 @@
|
|
|
858
858
|
return { useExistingMirror: false, reason: 'overlay_probe_failed', mirrorStatus };
|
|
859
859
|
}
|
|
860
860
|
if (getCurrentProjectId() !== projectId) return { useExistingMirror: false, reason: 'project_changed' };
|
|
861
|
-
const fileOverlays = buildSnapshotFileOverlays(overlayProject, focusFiles)
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
}
|
|
861
|
+
const fileOverlays = buildSnapshotFileOverlays(overlayProject, focusFiles).filter(file =>
|
|
862
|
+
!otWarmStart.ok || focusFiles.some(path => normalizeSnapshotPath(path) === normalizeSnapshotPath(file.path)));
|
|
863
|
+
if (!fileOverlays.length) return { useExistingMirror: false, reason: 'missing_current_overlay', mirrorStatus };
|
|
865
864
|
if (focusFiles.length && !focusFiles.every(path => {
|
|
866
865
|
const normalized = normalizeSnapshotPath(path);
|
|
867
866
|
return fileOverlays.some(file => normalizeSnapshotPath(file.path) === normalized);
|