codex-overleaf-link 2.6.0 → 2.6.5
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 +9 -9
- package/README.zh-CN.md +9 -9
- package/extension/bootstrap/manifest.template.json +1 -1
- package/extension/src/background.js +70 -0
- package/extension/src/content/composerAttachments.js +35 -8
- package/extension/src/content/contentRuntime.js +200 -51
- package/extension/src/content/diagnosticsController.js +77 -34
- package/extension/src/content/diagnosticsExport.js +1 -1
- package/extension/src/content/diagnosticsPanel.js +129 -42
- package/extension/src/content/generated/content.bundle.js +1283 -331
- package/extension/src/content/generated/content.bundle.meta.json +3 -3
- package/extension/src/content/localSkillsPanel.js +4 -2
- package/extension/src/content/markdownText.js +11 -9
- package/extension/src/content/modelPicker.js +28 -19
- package/extension/src/content/nativeCompatibilityController.js +23 -9
- package/extension/src/content/pageBridgeClient.js +5 -5
- package/extension/src/content/panelMaintenance.js +4 -0
- package/extension/src/content/panelRenderer.js +4 -1
- package/extension/src/content/providerSettingsDialog.js +26 -18
- package/extension/src/content/recentProjects.js +26 -16
- package/extension/src/content/runQueueScheduler.js +19 -9
- package/extension/src/content/runResultActions.js +51 -4
- package/extension/src/content/runReviewController.js +9 -3
- package/extension/src/content/scopedPersistencePanelState.js +34 -25
- package/extension/src/content/selectionContextView.js +30 -3
- package/extension/src/content/sharedSessionViewSync.js +9 -1
- package/extension/src/content/writebackOrchestrator.js +266 -50
- package/extension/src/content/writingStyleSettings.js +70 -17
- package/extension/src/page/overleafEditor.js +12 -3
- package/extension/src/page/overleafProjectSnapshot.js +56 -3
- package/extension/src/page/snapshotRouter.js +75 -66
- package/extension/src/page/treeOperations.js +200 -19
- package/extension/src/page/writebackRouter.js +152 -40
- package/extension/src/pageBridge.js +17 -7
- package/extension/src/shared/agentTranscript.js +23 -2
- package/extension/src/shared/auditRecords.js +1 -0
- package/extension/src/shared/compatibility.js +1 -1
- package/extension/src/shared/composerAttachmentDraft.js +22 -7
- package/extension/src/shared/failureReasons.js +15 -0
- package/extension/src/shared/i18n.js +16 -0
- package/extension/src/shared/pageRpcContract.js +1 -1
- package/extension/src/shared/projectFiles.js +2 -1
- package/extension/src/shared/scopedPersistenceBrowserAdapter.js +34 -0
- package/extension/src/shared/staleGuard.js +58 -0
- package/extension/src/shared/storageMigration.js +104 -1
- package/extension/styles/panel.css +191 -63
- package/native-host/src/codexSessionRunner.js +1 -0
- package/native-host/src/debugLog.js +27 -3
- package/native-host/src/index.js +42 -11
- package/native-host/src/localSkills.js +1 -1
- package/native-host/src/mirrorWorkspace.js +47 -3
- package/native-host/src/nativeEnvironment.js +27 -5
- package/native-host/src/providerRuntime.js +1 -0
- package/native-host/src/skills/reviewer-response/SKILL.md +65 -0
- package/native-host/src/taskRunnerRuntime.js +11 -3
- package/native-host/src/updateManager.js +24 -6
- package/native-host/src/writingStyleRuntime.js +1 -1
- package/package.json +1 -1
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
(function initCodexOverleafTreeOperations(root, factory) {
|
|
2
2
|
if (typeof module === 'object' && module.exports) {
|
|
3
|
-
module.exports = factory();
|
|
3
|
+
module.exports = factory(require('../shared/staleGuard'), require('../shared/otText'));
|
|
4
4
|
} else {
|
|
5
|
-
root.CodexOverleafTreeOperations = factory();
|
|
5
|
+
root.CodexOverleafTreeOperations = factory(root.CodexOverleafStaleGuard, root.CodexOverleafOtText);
|
|
6
6
|
}
|
|
7
|
-
})(typeof window !== 'undefined' ? window : globalThis, function treeOperationsFactory() {
|
|
7
|
+
})(typeof window !== 'undefined' ? window : globalThis, function treeOperationsFactory(StaleGuard, OtText) {
|
|
8
8
|
'use strict';
|
|
9
9
|
|
|
10
10
|
const TEXT_PATH_EXTENSION_PATTERN = '(?:tex|bib|sty|cls|bst|bbx|cbx|lbx|cfg|def|clo|ist|txt|md|latex)';
|
|
11
|
+
const ACTIVE_EDITOR_STABILITY_MS = 300;
|
|
11
12
|
|
|
12
13
|
function create({
|
|
13
14
|
window: windowDep,
|
|
@@ -15,6 +16,8 @@
|
|
|
15
16
|
normalizePath = fallbackNormalizeSafeProjectPath,
|
|
16
17
|
readActiveEditorText = () => '',
|
|
17
18
|
getActiveEditorIdentity = () => null,
|
|
19
|
+
getCodeMirrorEditorView = () => getActiveEditorIdentity()?.view,
|
|
20
|
+
getCodeMirrorEditorViews = () => [getCodeMirrorEditorView()].filter(Boolean),
|
|
18
21
|
activeEditorIdentityChanged = () => false,
|
|
19
22
|
getActiveFilePathFromEditorStore: readActiveFilePathFromEditorStore = () => ''
|
|
20
23
|
} = {}) {
|
|
@@ -93,10 +96,144 @@
|
|
|
93
96
|
}
|
|
94
97
|
|
|
95
98
|
function getProjectId() {
|
|
96
|
-
const match = window.location
|
|
99
|
+
const match = (window.location?.pathname || '').match(/\/project\/([^/]+)/);
|
|
97
100
|
return match ? decodeURIComponent(match[1]) : null;
|
|
98
101
|
}
|
|
99
102
|
|
|
103
|
+
function normalizeDocumentId(value) {
|
|
104
|
+
return typeof value === 'string' && /^[a-f0-9]{24}$/i.test(value) ? value.toLowerCase() : '';
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Navigation's broad scanners and cached basename maps are deliberately not
|
|
108
|
+
// evidence. Only the scoped project tree and literal native doc rows qualify.
|
|
109
|
+
function resolveTargetDocument(path, { projectId = getProjectId() } = {}) {
|
|
110
|
+
const failure = (status, reason) => ({ status, projectId, path, reason });
|
|
111
|
+
if (!path || normalizeSafeProjectPath(path) !== path || !projectId || getProjectId() !== projectId)
|
|
112
|
+
return failure('ambiguous', 'project_changed');
|
|
113
|
+
const records = [];
|
|
114
|
+
let truncated = false;
|
|
115
|
+
const seen = new Set();
|
|
116
|
+
function walk(folder, prefix, depth) {
|
|
117
|
+
if (!folder || typeof folder !== 'object') return;
|
|
118
|
+
if (depth > 7 || seen.has(folder) || records.length >= 120) { truncated = true; return; }
|
|
119
|
+
seen.add(folder);
|
|
120
|
+
const docs = folder.docs || [], folders = folder.folders || [];
|
|
121
|
+
if (!Array.isArray(docs) || !Array.isArray(folders)) { truncated = true; return; }
|
|
122
|
+
if (docs.length > 250 || folders.length > 250) truncated = true;
|
|
123
|
+
for (const doc of docs.slice(0, 250)) {
|
|
124
|
+
if (records.length >= 120) { truncated = true; break; }
|
|
125
|
+
const name = doc?.name, id = normalizeDocumentId(doc?._id);
|
|
126
|
+
const filePath = typeof name === 'string' && !/[/\\]/.test(name) ? normalizeSafeProjectPath(prefix + name) : '';
|
|
127
|
+
if (!filePath || !id) { truncated = true; continue; }
|
|
128
|
+
records.push({ path: filePath, id, source: 'project-tree' });
|
|
129
|
+
}
|
|
130
|
+
for (const child of folders.slice(0, 250)) {
|
|
131
|
+
const name = child?.name;
|
|
132
|
+
if (typeof name !== 'string' || /[/\\]/.test(name) || !normalizeSafeProjectPath(prefix + name)) {
|
|
133
|
+
truncated = true;
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
walk(child, prefix + name + '/', depth + 1);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const project = window._ide?.project;
|
|
140
|
+
if (project?._id && project._id !== projectId) return failure('ambiguous', 'project_changed');
|
|
141
|
+
const editorProjectId = document.querySelector?.('[data-project-id]')?.getAttribute?.('data-project-id');
|
|
142
|
+
if (editorProjectId && editorProjectId !== projectId) return failure('ambiguous', 'project_changed');
|
|
143
|
+
if (project?._id === projectId && project.rootFolder) {
|
|
144
|
+
const roots = Array.isArray(project.rootFolder) ? project.rootFolder : [project.rootFolder];
|
|
145
|
+
if (roots.length !== 1) truncated = true;
|
|
146
|
+
for (const root of roots.slice(0, 1)) walk(root, '', 0);
|
|
147
|
+
}
|
|
148
|
+
const root = document.querySelector?.('[data-testid="file-tree-list-root"]');
|
|
149
|
+
const nodes = root?.querySelectorAll?.('[data-file-type="doc"][data-file-id]') || [];
|
|
150
|
+
if (nodes.length >= 120) truncated = true;
|
|
151
|
+
for (let index = 0; index < Math.min(nodes.length, 120); index += 1) {
|
|
152
|
+
const node = nodes[index];
|
|
153
|
+
const row = node.closest?.('[role="treeitem"]');
|
|
154
|
+
if (!row || row.querySelector?.('[data-file-type="doc"][data-file-id]') !== node) continue;
|
|
155
|
+
const filePath = readNativeTreePath(node), id = normalizeDocumentId(node.getAttribute?.('data-file-id'));
|
|
156
|
+
if (!filePath || !id) { truncated = true; continue; }
|
|
157
|
+
records.push({ path: filePath, id, source: 'native-tree' });
|
|
158
|
+
}
|
|
159
|
+
const matches = records.filter(record => record.path === path);
|
|
160
|
+
const ids = new Set(matches.map(record => record.id));
|
|
161
|
+
if (ids.size > 1 || matches.some(match => records.some(record => record.id === match.id && record.path !== path)))
|
|
162
|
+
return failure('ambiguous', 'identity_conflict');
|
|
163
|
+
if (truncated || ids.size !== 1) return failure('unavailable', 'identity_unavailable');
|
|
164
|
+
return { status: 'known', projectId, path, documentId: matches[0].id, source: matches[0].source };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function readNavigationDocumentIds() {
|
|
168
|
+
const store = window.overleaf?.unstable?.store || window.Overleaf?.unstable?.store;
|
|
169
|
+
const values = [window._ide?.editor?.open_doc_id, window._ide?.editor?.openDocId];
|
|
170
|
+
for (const key of ['editor.open_doc_id', 'editor.openDocId']) {
|
|
171
|
+
try { values.push(store?.get?.(key)); } catch (_error) { /* No positive evidence from a store hint. */ }
|
|
172
|
+
}
|
|
173
|
+
return values.filter(value => typeof value === 'string' && value.length).map(value => value.toLowerCase());
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function captureEditorDocument({ path, projectId = getProjectId() } = {}) {
|
|
177
|
+
const fail = (identityState, reason) => ({ ok: false, code: 'document_identity_mismatch', identityState, reason });
|
|
178
|
+
try {
|
|
179
|
+
const target = resolveTargetDocument(path, { projectId });
|
|
180
|
+
if (target.status === 'ambiguous') return fail('mismatch', target.reason);
|
|
181
|
+
const hints = readNavigationDocumentIds();
|
|
182
|
+
if (new Set(hints).size > 1 || (target.status === 'known' && hints.some(id => id !== target.documentId)))
|
|
183
|
+
return fail('unavailable', 'navigation_conflict');
|
|
184
|
+
const views = [...new Set(getCodeMirrorEditorViews())];
|
|
185
|
+
if (views.length > 1) return fail('mismatch', 'identity_ambiguous');
|
|
186
|
+
const view = views[0], state = view?.state, doc = state?.doc;
|
|
187
|
+
if (!view || view.dom?.isConnected === false || typeof view.dispatch !== 'function' || !doc)
|
|
188
|
+
return fail('unavailable', 'identity_unavailable');
|
|
189
|
+
if (!Array.isArray(state.values)) return fail('unavailable', 'identity_unavailable');
|
|
190
|
+
if (state.values.length > 2048) return fail('mismatch', 'identity_ambiguous');
|
|
191
|
+
const entries = state.values.filter(value => value && typeof value === 'object'
|
|
192
|
+
&& Object.prototype.hasOwnProperty.call(value, 'ranges') && value.ranges != null
|
|
193
|
+
&& Object.prototype.hasOwnProperty.call(value, 'threads'));
|
|
194
|
+
if (!entries.length) return fail('unavailable', 'identity_unavailable');
|
|
195
|
+
if (entries.length !== 1) return fail('mismatch', 'identity_ambiguous');
|
|
196
|
+
const entry = entries[0], documentId = normalizeDocumentId(entry.ranges?.docId);
|
|
197
|
+
if (!Object.prototype.hasOwnProperty.call(entry, 'threads') || !Array.isArray(entry.ranges?.changes)
|
|
198
|
+
|| !Array.isArray(entry.ranges?.comments) || !documentId) return fail('mismatch', 'identity_conflict');
|
|
199
|
+
// Overleaf installs ranges asynchronously. A stale switch timeout may
|
|
200
|
+
// attach a previous document's ranges to a newly mounted state's text.
|
|
201
|
+
if (readNavigationDocumentIds().some(id => id !== documentId)) return fail('unavailable', 'navigation_conflict');
|
|
202
|
+
if (target.status !== 'known') return fail('unavailable', target.reason);
|
|
203
|
+
const documentIdentity = { version: 1, source: 'cm-ranges-v1', projectId, path,
|
|
204
|
+
targetDocumentId: target.documentId, documentId };
|
|
205
|
+
const decision = StaleGuard.assessDocumentProvenance({ path, projectId, documentIdentity });
|
|
206
|
+
if (!decision.ok) return { ...decision, reason: 'identity_conflict' };
|
|
207
|
+
const text = doc.toString();
|
|
208
|
+
if (typeof text !== 'string' || !Number.isSafeInteger(doc.length) || doc.length !== text.length)
|
|
209
|
+
return fail('unavailable', 'unread_document');
|
|
210
|
+
// The target resolution and text read are synchronous. Emission and
|
|
211
|
+
// dispatch resolve again; retain the cheap local capture checks here.
|
|
212
|
+
const currentViews = [...new Set(getCodeMirrorEditorViews())];
|
|
213
|
+
if (currentViews.length !== 1 || currentViews[0] !== view || view.state !== state || state.doc !== doc
|
|
214
|
+
|| getProjectId() !== projectId
|
|
215
|
+
|| readNavigationDocumentIds().some(id => id !== documentId)) return fail('unavailable', 'capture_changed');
|
|
216
|
+
return { ok: true, identityState: 'match', text, documentIdentity, view, state, doc };
|
|
217
|
+
} catch (_error) {
|
|
218
|
+
return fail('unavailable', 'unread_document');
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function isCaptureCurrent(capture) {
|
|
223
|
+
if (!capture?.ok || !capture.documentIdentity) return false;
|
|
224
|
+
const current = captureEditorDocument(capture.documentIdentity);
|
|
225
|
+
return current.ok && current.view === capture.view && current.state === capture.state && current.doc === capture.doc
|
|
226
|
+
&& current.text === capture.text && current.documentIdentity.documentId === capture.documentIdentity.documentId;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function serializeEditorCapture(capture) {
|
|
230
|
+
if (!capture?.ok || typeof capture.text !== 'string')
|
|
231
|
+
return { ok: false, code: 'document_identity_mismatch', identityState: 'unavailable' };
|
|
232
|
+
const contentSha256 = OtText.hashText(capture.text);
|
|
233
|
+
if (!isCaptureCurrent(capture)) return { ok: false, code: 'document_identity_mismatch', identityState: 'unavailable' };
|
|
234
|
+
return { ok: true, documentIdentity: { ...capture.documentIdentity, contentSha256 } };
|
|
235
|
+
}
|
|
236
|
+
|
|
100
237
|
function readNativeTreePath(node) {
|
|
101
238
|
const row = node?.closest?.('[role="treeitem"]');
|
|
102
239
|
const root = document.querySelector?.('[data-testid="file-tree-list-root"]');
|
|
@@ -761,13 +898,18 @@
|
|
|
761
898
|
}
|
|
762
899
|
|
|
763
900
|
function collectProjectTextPaths(activePath) {
|
|
901
|
+
const docRecords = collectDocRecords();
|
|
764
902
|
const rawPaths = [
|
|
765
903
|
activePath,
|
|
766
|
-
...
|
|
904
|
+
...docRecords.map(record => record.path),
|
|
767
905
|
...collectInternalProjectPaths(),
|
|
768
906
|
...collectDomProjectPaths()
|
|
769
907
|
];
|
|
770
|
-
|
|
908
|
+
const paths = window.CodexOverleafProjectFiles.collectUniqueTextPaths(rawPaths, 80);
|
|
909
|
+
if (docRecords.truncated) {
|
|
910
|
+
paths.truncated = true;
|
|
911
|
+
}
|
|
912
|
+
return paths;
|
|
771
913
|
}
|
|
772
914
|
|
|
773
915
|
function collectDocRecords(options = {}) {
|
|
@@ -784,6 +926,8 @@
|
|
|
784
926
|
seen.add(key);
|
|
785
927
|
records.push(record);
|
|
786
928
|
if (records.length >= 120) {
|
|
929
|
+
// The internal collector also stops here, so exhaustion is unproven.
|
|
930
|
+
records.truncated = true;
|
|
787
931
|
break;
|
|
788
932
|
}
|
|
789
933
|
}
|
|
@@ -1381,28 +1525,61 @@
|
|
|
1381
1525
|
|
|
1382
1526
|
async function waitForActiveEditorText(filePath, timeoutMs, options = {}) {
|
|
1383
1527
|
const deadline = Date.now() + timeoutMs;
|
|
1528
|
+
const projectId = options.projectId || getProjectId();
|
|
1529
|
+
const identityDeadline = Math.min(deadline, Date.now() + ACTIVE_EDITOR_STABILITY_MS);
|
|
1384
1530
|
let lastText = '';
|
|
1531
|
+
let stableView = null, stablePath = '', stableDocumentId = '', stableSince = 0, mismatch = null;
|
|
1385
1532
|
while (Date.now() < deadline) {
|
|
1386
|
-
|
|
1387
|
-
const
|
|
1533
|
+
if (getProjectId() !== projectId) return { ok: false, code: 'document_identity_mismatch', reason: 'project_changed' };
|
|
1534
|
+
const activePath = options.passive ? getEditorStoreFilePath({ passive: true }) : getActiveFilePath();
|
|
1535
|
+
const activeFileMatches = Boolean(activePath) && (!filePath || activePath === filePath);
|
|
1536
|
+
const capture = captureEditorDocument({ path: filePath || activePath, projectId });
|
|
1537
|
+
mismatch = capture.identityState === 'mismatch' || capture.reason === 'navigation_conflict'
|
|
1538
|
+
? { ...capture, identityState: 'mismatch' } : null;
|
|
1539
|
+
let text, identity, observed;
|
|
1540
|
+
try {
|
|
1541
|
+
identity = getActiveEditorIdentity();
|
|
1542
|
+
text = capture.ok ? capture.text : readActiveEditorText();
|
|
1543
|
+
if (identity?.type === 'codemirror-view') observed = identity.doc?.toString?.();
|
|
1544
|
+
else if (identity?.type === 'textarea') observed = identity.node?.value;
|
|
1545
|
+
else if (identity?.type === 'contenteditable') observed = identity.node?.innerText ?? identity.node?.textContent;
|
|
1546
|
+
} catch (_error) { text = undefined; }
|
|
1547
|
+
const view = capture.ok ? capture.view : identity?.view || identity?.node;
|
|
1388
1548
|
lastText = text;
|
|
1389
|
-
const knownEmptyEditor = options.allowEmpty === true && typeof text === 'string' &&
|
|
1390
|
-
&&
|
|
1549
|
+
const knownEmptyEditor = options.allowEmpty === true && typeof text === 'string' && !text.trim()
|
|
1550
|
+
&& typeof observed === 'string' && observed === text;
|
|
1391
1551
|
const textReady = options.requireEmpty === true ? knownEmptyEditor
|
|
1392
1552
|
: knownEmptyEditor || window.CodexOverleafProjectFiles.isUsableProjectFileContent(text);
|
|
1393
|
-
const signatureChanged = !options.notSignature || contentSignature(text) !== options.notSignature;
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1553
|
+
const signatureChanged = capture.ok || !options.notSignature || contentSignature(text) !== options.notSignature;
|
|
1554
|
+
const identityReady = capture.ok || (capture.identityState === 'unavailable' && capture.reason !== 'navigation_conflict'
|
|
1555
|
+
&& Date.now() >= identityDeadline);
|
|
1556
|
+
if (activeFileMatches && view && textReady && signatureChanged && identityReady) {
|
|
1557
|
+
const documentId = capture.documentIdentity?.documentId || '';
|
|
1558
|
+
if (view !== stableView || activePath !== stablePath || documentId !== stableDocumentId) {
|
|
1559
|
+
stableView = view; stablePath = activePath; stableDocumentId = documentId; stableSince = Date.now();
|
|
1560
|
+
} else if (Date.now() - stableSince >= ACTIVE_EDITOR_STABILITY_MS) {
|
|
1561
|
+
const provenance = StaleGuard.assessDocumentProvenance({ path: activePath, text, references: options.references,
|
|
1562
|
+
projectId, documentIdentity: capture.documentIdentity });
|
|
1563
|
+
if (provenance.ok) {
|
|
1564
|
+
if (!capture.ok) return { ok: true, text, identityState: 'fallback' };
|
|
1565
|
+
const serialized = serializeEditorCapture(capture);
|
|
1566
|
+
if (serialized.ok) return { ok: true, text, capture, documentIdentity: serialized.documentIdentity, identityState: 'match' };
|
|
1567
|
+
mismatch = serialized;
|
|
1568
|
+
stableView = null;
|
|
1569
|
+
} else {
|
|
1570
|
+
mismatch = provenance;
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
} else {
|
|
1574
|
+
stableView = null;
|
|
1399
1575
|
}
|
|
1400
|
-
await delay(150);
|
|
1576
|
+
await delay(Math.max(0, Math.min(150, deadline - Date.now())));
|
|
1401
1577
|
}
|
|
1402
1578
|
return {
|
|
1403
1579
|
ok: false,
|
|
1404
1580
|
text: lastText,
|
|
1405
|
-
|
|
1581
|
+
...(mismatch || {}),
|
|
1582
|
+
reason: mismatch?.code || `Editor content was not ready for ${filePath || 'active file'}; last length ${String(lastText || '').length}`
|
|
1406
1583
|
};
|
|
1407
1584
|
}
|
|
1408
1585
|
|
|
@@ -1588,6 +1765,10 @@
|
|
|
1588
1765
|
getEditorStoreFilePath,
|
|
1589
1766
|
getRecentFileTreeSelectionPath,
|
|
1590
1767
|
getProjectId,
|
|
1768
|
+
resolveTargetDocument,
|
|
1769
|
+
captureEditorDocument,
|
|
1770
|
+
isCaptureCurrent,
|
|
1771
|
+
serializeEditorCapture,
|
|
1591
1772
|
navigateToFile,
|
|
1592
1773
|
openFileByPath,
|
|
1593
1774
|
projectPathExists,
|
|
@@ -1612,5 +1793,5 @@
|
|
|
1612
1793
|
move: ['moveEntity', 'moveFile', 'moveDoc'], delete: ['deleteEntity', 'deleteFile', 'deleteDoc', 'removeEntity']
|
|
1613
1794
|
}[type] || [];
|
|
1614
1795
|
}
|
|
1615
|
-
return { create, fileTreeMethodNames };
|
|
1796
|
+
return { create, fileTreeMethodNames, ACTIVE_EDITOR_STABILITY_MS };
|
|
1616
1797
|
});
|