codex-overleaf-link 2.5.1 → 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.
Files changed (111) hide show
  1. package/README.md +149 -398
  2. package/README.zh-CN.md +153 -404
  3. package/extension/bootstrap/manifest.template.json +1 -1
  4. package/extension/src/background.js +148 -3
  5. package/extension/src/backgroundSharedSessions.js +55 -2
  6. package/extension/src/backgroundUpdateCoordinator.js +128 -12
  7. package/extension/src/content/activeTurnControl.js +164 -7
  8. package/extension/src/content/composerAttachments.js +46 -10
  9. package/extension/src/content/composerPanel.js +92 -12
  10. package/extension/src/content/contentRuntime.js +1114 -321
  11. package/extension/src/content/contextTray.js +8 -2
  12. package/extension/src/content/contextUsageView.js +267 -0
  13. package/extension/src/content/diagnosticsController.js +77 -34
  14. package/extension/src/content/diagnosticsExport.js +1 -1
  15. package/extension/src/content/diagnosticsPanel.js +147 -42
  16. package/extension/src/content/generated/content.bundle.js +5761 -1237
  17. package/extension/src/content/generated/content.bundle.meta.json +6 -3
  18. package/extension/src/content/legacyGlobalRegistry.js +4 -0
  19. package/extension/src/content/localSkillsPanel.js +6 -4
  20. package/extension/src/content/markdownDomRenderer.js +5 -3
  21. package/extension/src/content/markdownText.js +53 -14
  22. package/extension/src/content/modelPicker.js +29 -19
  23. package/extension/src/content/nativeCompatibilityController.js +52 -19
  24. package/extension/src/content/otWarmMirror.js +1 -1
  25. package/extension/src/content/pageBridgeClient.js +7 -7
  26. package/extension/src/content/panelMaintenance.js +10 -2
  27. package/extension/src/content/panelRenderer.js +55 -28
  28. package/extension/src/content/pendingInputView.js +1 -1
  29. package/extension/src/content/projectSettingsCoordinator.js +30 -6
  30. package/extension/src/content/providerSettingsDialog.js +28 -19
  31. package/extension/src/content/recentProjects.js +30 -19
  32. package/extension/src/content/runActivitySummary.js +122 -14
  33. package/extension/src/content/runCompletionMeta.js +194 -6
  34. package/extension/src/content/runController.js +2 -1
  35. package/extension/src/content/runFailureNotice.js +8 -1
  36. package/extension/src/content/runPresence.js +18 -8
  37. package/extension/src/content/runQueueScheduler.js +27 -13
  38. package/extension/src/content/runRecoveryActions.js +2 -1
  39. package/extension/src/content/runResultActions.js +73 -24
  40. package/extension/src/content/runReviewController.js +102 -37
  41. package/extension/src/content/runTimelineView.js +224 -25
  42. package/extension/src/content/scopedPersistencePanelState.js +124 -46
  43. package/extension/src/content/selectionContextView.js +30 -3
  44. package/extension/src/content/sensitivePreflight.js +14 -1
  45. package/extension/src/content/sessionManager.js +49 -3
  46. package/extension/src/content/sessionMenuView.js +54 -18
  47. package/extension/src/content/sessionPersistence.js +25 -5
  48. package/extension/src/content/settingsPanel.js +15 -2
  49. package/extension/src/content/settingsWorkbench.js +127 -89
  50. package/extension/src/content/sharedSessionViewSync.js +13 -4
  51. package/extension/src/content/subagentActivityView.js +23 -7
  52. package/extension/src/content/updateNotice.js +60 -6
  53. package/extension/src/content/writebackOrchestrator.js +301 -72
  54. package/extension/src/content/writingStyleSettings.js +70 -17
  55. package/extension/src/page/compileBridge.js +193 -180
  56. package/extension/src/page/overleafCapabilities.js +4 -1
  57. package/extension/src/page/overleafEditor.js +12 -3
  58. package/extension/src/page/overleafProjectSnapshot.js +56 -3
  59. package/extension/src/page/snapshotRouter.js +75 -66
  60. package/extension/src/page/textCoordinates.js +17 -1
  61. package/extension/src/page/textFileCreator.js +9 -1
  62. package/extension/src/page/treeOperations.js +200 -19
  63. package/extension/src/page/writebackRouter.js +172 -113
  64. package/extension/src/pageBridge.js +124 -73
  65. package/extension/src/popup.js +1 -1
  66. package/extension/src/shared/agentTranscript.js +372 -18
  67. package/extension/src/shared/auditRecords.js +3 -0
  68. package/extension/src/shared/compatibility.js +1 -1
  69. package/extension/src/shared/compileAdapter.js +58 -17
  70. package/extension/src/shared/composerAttachmentDraft.js +27 -7
  71. package/extension/src/shared/contextUsage.js +125 -0
  72. package/extension/src/shared/failureReasons.js +57 -3
  73. package/extension/src/shared/i18n.js +315 -29
  74. package/extension/src/shared/lineReferences.js +38 -31
  75. package/extension/src/shared/pageRpcContract.js +1 -1
  76. package/extension/src/shared/panelIcons.js +39 -0
  77. package/extension/src/shared/projectFiles.js +2 -1
  78. package/extension/src/shared/reviewing.js +130 -1
  79. package/extension/src/shared/runActivityModel.js +70 -4
  80. package/extension/src/shared/runExecutionSnapshot.js +13 -0
  81. package/extension/src/shared/scopedPersistenceBrowserAdapter.js +34 -0
  82. package/extension/src/shared/sessionState.js +63 -4
  83. package/extension/src/shared/sessionTitle.js +14 -1
  84. package/extension/src/shared/sharedSessionBridge.js +81 -13
  85. package/extension/src/shared/staleGuard.js +130 -63
  86. package/extension/src/shared/storageDb.js +35 -3
  87. package/extension/src/shared/storageMigration.js +111 -2
  88. package/extension/src/shared/storageRunActions.js +62 -8
  89. package/extension/src/shared/undoOperations.js +126 -28
  90. package/extension/src/shared/updateRuntimeIdentity.js +16 -2
  91. package/extension/src/shared/writebackSettlement.js +21 -3
  92. package/extension/styles/panel.css +1293 -549
  93. package/native-host/src/bootstrapUpdate.js +52 -16
  94. package/native-host/src/chatBridgeRequest.js +60 -6
  95. package/native-host/src/chatBridgeResponse.js +10 -1
  96. package/native-host/src/chatCompletionsBridge.js +29 -2
  97. package/native-host/src/codexPromptAssembly.js +86 -118
  98. package/native-host/src/codexSessionRunner.js +127 -17
  99. package/native-host/src/debugLog.js +27 -3
  100. package/native-host/src/index.js +42 -11
  101. package/native-host/src/localSkills.js +1 -1
  102. package/native-host/src/mirrorWorkspace.js +47 -3
  103. package/native-host/src/nativeEnvironment.js +27 -5
  104. package/native-host/src/providerContextError.js +20 -0
  105. package/native-host/src/providerRuntime.js +1 -0
  106. package/native-host/src/skills/reviewer-response/SKILL.md +65 -0
  107. package/native-host/src/taskRunnerRuntime.js +28 -8
  108. package/native-host/src/textPatch.js +473 -377
  109. package/native-host/src/updateManager.js +144 -21
  110. package/native-host/src/writingStyleRuntime.js +1 -1
  111. package/package.json +5 -8
@@ -19,9 +19,14 @@
19
19
  <div class="codex-diagnostics-wrap">
20
20
  <button type="button" class="codex-diagnostics-trigger" data-diagnostics-menu title="Diagnostics" aria-label="Diagnostics" aria-expanded="false">
21
21
  <span class="codex-diagnostics-dot" data-diagnostics-health-dot data-health="unknown"></span>
22
+ <span class="codex-diagnostics-label" data-diagnostics-health-label></span>
22
23
  </button>
23
24
  <div class="codex-diagnostics-menu" data-diagnostics-popover hidden>
24
25
  <div class="codex-diagnostics-hint" data-i18n="diagnosticsHint">Use when Codex cannot run, write, or read files</div>
26
+ <button type="button" data-refresh>
27
+ <span class="codex-diagnostics-refresh-title">${options.icons?.svg?.('refresh') || ''}<span data-i18n="refreshProbeTitle">Refresh file status</span></span>
28
+ <small data-i18n="refreshProbeSubtitle">Re-reads Overleaf state; does not sync or modify files</small>
29
+ </button>
25
30
  <button type="button" class="codex-diagnostics-runall" data-diagnostics-run-all>
26
31
  <span data-i18n="diagnosticsRunAllTitle">Run all checks</span>
27
32
  <small data-i18n="diagnosticsRunAllSubtitle">Connection, write access, project read, OT mirror</small>
@@ -81,6 +86,10 @@
81
86
 
82
87
  function bindStaticActions(instance) {
83
88
  const root = instance.container;
89
+ root.querySelector('[data-refresh]')?.addEventListener('click', () => {
90
+ closeMenu(instance);
91
+ instance.callbacks.onRefresh?.();
92
+ });
84
93
  root.querySelector('[data-diagnostics-menu]')?.addEventListener('click', () => toggleMenu(instance));
85
94
  root.querySelector('[data-diagnostics-run-all]')?.addEventListener('click', () => instance.callbacks.onRunAll?.());
86
95
  root.querySelector('[data-diagnostics-native-env]')?.addEventListener('click', () => instance.callbacks.onNativeEnvironment?.());
@@ -173,11 +182,18 @@
173
182
  const details = root.querySelector('[data-diagnostics-result-details]');
174
183
  const scroll = root.querySelector('.codex-diagnostics-result-scroll');
175
184
  const open = details?.open, scrollTop = scroll?.scrollTop;
176
- const checks = Array.from(root.querySelectorAll('.codex-diagnostics-check'), node => node.open);
185
+ const checks = Array.from(root.querySelectorAll('.codex-diagnostics-check'), node => ({
186
+ open: node.open,
187
+ technicalOpen: node.querySelector('.codex-diagnostics-technical')?.open
188
+ }));
177
189
  showResult(instance, result);
178
190
  if (details) details.open = open;
179
191
  root.querySelectorAll('.codex-diagnostics-check').forEach((node, index) => {
180
- if (index < checks.length) node.open = checks[index];
192
+ if (index < checks.length) {
193
+ node.open = checks[index].open;
194
+ const technical = node.querySelector('.codex-diagnostics-technical');
195
+ if (technical) technical.open = checks[index].technicalOpen;
196
+ }
181
197
  });
182
198
  if (scroll) scroll.scrollTop = scrollTop;
183
199
  }
@@ -194,45 +210,48 @@
194
210
  root.hidden = false;
195
211
  root.dataset.status = result.status || 'info';
196
212
  root.setAttribute('aria-label', result.title || t(instance, 'diagnosticsResult'));
197
- root.querySelector('[data-diagnostics-result-title]').textContent = result.title || t(instance, 'diagnosticsResult');
213
+ const titleNode = root.querySelector('[data-diagnostics-result-title]');
214
+ const dot = document.createElement('span');
215
+ dot.className = 'codex-diagnostics-status-dot';
216
+ dot.setAttribute('aria-hidden', 'true');
217
+ const titleText = document.createElement('span');
218
+ titleText.className = 'codex-diagnostics-result-title-text';
219
+ titleText.textContent = result.title || t(instance, 'diagnosticsResult');
220
+ titleNode.replaceChildren(dot, titleText);
198
221
  root.querySelector('[data-diagnostics-result-subtitle]').textContent = result.subtitle || '';
199
222
 
200
223
  const body = root.querySelector('[data-diagnostics-result-body]');
201
224
  body.textContent = '';
202
- if (result.summary) {
203
- appendParagraph(body, result.summary);
225
+ const facts = Array.isArray(result.facts) ? result.facts.filter(fact => fact?.label) : [];
226
+ const notes = [
227
+ ...(Array.isArray(result.notes) ? result.notes : []),
228
+ ...(Array.isArray(result.bullets) ? result.bullets : [])
229
+ ].filter(Boolean);
230
+ const hasChecks = Array.isArray(result.checks) && result.checks.length > 0;
231
+ if (result.summary && !(result.status === 'completed' && facts.length)) {
232
+ appendParagraph(body, result.summary, 'codex-diagnostics-summary');
204
233
  }
205
234
  // Aggregated health report: one status row per check (Run all checks).
206
- if (Array.isArray(result.checks) && result.checks.length) {
207
- renderCheckRows(body, result.checks);
208
- } else if (!result.summary) {
235
+ if (hasChecks) {
236
+ renderCheckRows(instance, body, result.checks);
237
+ } else if (!result.summary && !facts.length && !notes.length) {
209
238
  appendParagraph(body, t(instance, 'diagnosticsNoResult'));
210
239
  }
211
- if (Array.isArray(result.bullets) && result.bullets.length) {
212
- const list = document.createElement('ul');
213
- for (const item of result.bullets) {
214
- const li = document.createElement('li');
215
- li.textContent = item;
216
- list.append(li);
217
- }
218
- body.append(list);
240
+ if (facts.length) {
241
+ renderFacts(body, facts);
242
+ }
243
+ if (notes.length) {
244
+ renderNotes(body, notes);
219
245
  }
220
246
  if (result.nextStep) {
221
- const next = document.createElement('p');
222
- next.className = 'codex-diagnostics-next-step';
223
- next.textContent = `${t(instance, 'nextStepPrefix')}${result.nextStep}`;
224
- body.append(next);
247
+ appendNextStep(instance, body, result.nextStep, 'p', 'codex-diagnostics-next-step');
225
248
  }
226
249
  if (result.installCommand) {
227
250
  renderInstallCommand(instance, body, result.installCommand);
228
251
  }
229
252
 
230
253
  const details = root.querySelector('[data-diagnostics-result-details]');
231
- const technical = root.querySelector('[data-diagnostics-result-technical]');
232
- const technicalText = String(result.technical || '').trim();
233
- details.open = false;
234
- details.hidden = !technicalText;
235
- technical.textContent = technicalText;
254
+ renderTechnicalDetails(details, result.technical);
236
255
  closeMenu(instance);
237
256
  openFloating(instance, root, 400);
238
257
  if (wasHidden) root.querySelector('[data-diagnostics-result-close]')?.focus({ preventScroll: true });
@@ -315,14 +334,14 @@
315
334
  const wrap = document.createElement('div');
316
335
  wrap.className = 'codex-install-command';
317
336
 
318
- const label = document.createElement('div');
337
+ const head = document.createElement('div');
338
+ head.className = 'codex-install-command-head';
339
+ const label = document.createElement('span');
319
340
  label.className = 'codex-install-command-label';
320
341
  label.textContent = t(instance, 'runInTerminal');
321
- wrap.append(label);
322
342
 
323
343
  const code = document.createElement('code');
324
344
  code.textContent = command;
325
- wrap.append(code);
326
345
 
327
346
  const copyButton = document.createElement('button');
328
347
  copyButton.type = 'button';
@@ -334,18 +353,86 @@
334
353
  copyButton.textContent = t(instance, 'copyInstallCommand');
335
354
  }, 1400);
336
355
  });
337
- wrap.append(copyButton);
356
+ head.append(label, copyButton);
357
+ wrap.append(head, code);
338
358
 
339
359
  container.append(wrap);
340
360
  }
341
361
 
342
- function appendParagraph(container, text) {
362
+ function appendParagraph(container, text, className) {
343
363
  const paragraph = document.createElement('p');
364
+ if (className) {
365
+ paragraph.className = className;
366
+ }
344
367
  paragraph.textContent = text;
345
368
  container.append(paragraph);
346
369
  }
347
370
 
348
- // Map a result status to a coarse health bucket used for the row glyph + the
371
+ function appendNextStep(instance, container, text, tagName, className) {
372
+ const next = document.createElement(tagName);
373
+ next.className = className;
374
+ const label = document.createElement('span');
375
+ label.className = 'codex-diagnostics-next-label';
376
+ label.textContent = t(instance, 'nextStepPrefix');
377
+ next.append(label, document.createTextNode(text));
378
+ container.append(next);
379
+ }
380
+
381
+ // Facts pair a label and value, with optional tone and path presentation.
382
+ function renderFacts(container, facts) {
383
+ const list = document.createElement('dl');
384
+ list.className = 'codex-diagnostics-facts';
385
+ for (const fact of facts) {
386
+ const term = document.createElement('dt');
387
+ term.textContent = fact.label;
388
+ const value = document.createElement('dd');
389
+ const text = String(fact.value ?? '');
390
+ if (fact.kind === 'path') {
391
+ value.textContent = shortenPath(text);
392
+ value.title = text;
393
+ } else {
394
+ value.textContent = text;
395
+ }
396
+ if (fact.tone) {
397
+ value.dataset.tone = fact.tone;
398
+ }
399
+ list.append(term, value);
400
+ }
401
+ container.append(list);
402
+ }
403
+
404
+ // Shorten only the display; the full path stays in title and technical details.
405
+ function shortenPath(path) {
406
+ if (path.length <= 36) {
407
+ return path;
408
+ }
409
+ const parts = path.split('/');
410
+ if (parts.length < 5) {
411
+ return path;
412
+ }
413
+ const short = `${parts.slice(0, 3).join('/')}/…/${parts[parts.length - 1]}`;
414
+ return short.length < path.length ? short : path;
415
+ }
416
+
417
+ function renderNotes(container, notes) {
418
+ const list = document.createElement('ul');
419
+ list.className = 'codex-diagnostics-notes';
420
+ for (const note of notes) {
421
+ const item = document.createElement('li');
422
+ item.textContent = note;
423
+ list.append(item);
424
+ }
425
+ container.append(list);
426
+ }
427
+
428
+ function renderTechnicalDetails(details, value) {
429
+ const text = String(value || '').trim();
430
+ details.open = false;
431
+ details.hidden = !text;
432
+ details.querySelector('pre').textContent = text;
433
+ }
434
+
435
+ // Map a result status to a coarse health bucket used for the row dot + the
349
436
  // overall dot. 'completed' reads as a pass; anything not-ok is attention.
350
437
  function healthBucket(status) {
351
438
  if (status === 'completed' || status === 'ok') return 'ok';
@@ -354,10 +441,10 @@
354
441
  return 'info';
355
442
  }
356
443
 
357
- // Render the aggregated report as one scannable row per check: a status glyph
444
+ // Render the aggregated report as one scannable row per check: a status dot
358
445
  // (via CSS [data-status]), a plain-language title + summary, and an optional
359
- // actionable next step.
360
- function renderCheckRows(container, checks) {
446
+ // actionable next step, install command and technical evidence.
447
+ function renderCheckRows(instance, container, checks) {
361
448
  const list = document.createElement('div');
362
449
  list.className = 'codex-diagnostics-checks';
363
450
  for (const check of checks) {
@@ -368,16 +455,16 @@
368
455
  row.open = row.dataset.status === 'warn' || row.dataset.status === 'fail';
369
456
  const heading = document.createElement('summary');
370
457
 
371
- const glyph = document.createElement('span');
372
- glyph.className = 'codex-diagnostics-check-glyph';
373
- glyph.setAttribute('aria-hidden', 'true');
458
+ const dot = document.createElement('span');
459
+ dot.className = 'codex-diagnostics-check-dot';
460
+ dot.setAttribute('aria-hidden', 'true');
374
461
 
375
462
  const textWrap = document.createElement('div');
376
463
  textWrap.className = 'codex-diagnostics-check-text';
377
464
  const title = document.createElement('div');
378
465
  title.className = 'codex-diagnostics-check-title';
379
466
  title.textContent = check.title || '';
380
- heading.append(glyph, title);
467
+ heading.append(dot, title);
381
468
  if (check.summary) {
382
469
  const summary = document.createElement('div');
383
470
  summary.className = 'codex-diagnostics-check-summary';
@@ -385,10 +472,19 @@
385
472
  textWrap.append(summary);
386
473
  }
387
474
  if (check.nextStep) {
388
- const next = document.createElement('div');
389
- next.className = 'codex-diagnostics-check-next';
390
- next.textContent = `→ ${check.nextStep}`;
391
- textWrap.append(next);
475
+ appendNextStep(instance, textWrap, check.nextStep, 'div', 'codex-diagnostics-check-next');
476
+ }
477
+ if (check.installCommand) {
478
+ renderInstallCommand(instance, textWrap, check.installCommand);
479
+ }
480
+ if (check.technical) {
481
+ const details = document.createElement('details');
482
+ details.className = 'codex-diagnostics-technical';
483
+ const summary = document.createElement('summary');
484
+ summary.textContent = t(instance, 'technicalDetails');
485
+ details.append(summary, document.createElement('pre'));
486
+ renderTechnicalDetails(details, check.technical);
487
+ textWrap.append(details);
392
488
  }
393
489
 
394
490
  row.append(heading, textWrap);
@@ -488,6 +584,15 @@
488
584
  const tooltip = t(instance, tooltipKey);
489
585
  trigger.title = tooltip;
490
586
  trigger.setAttribute('aria-label', tooltip);
587
+ trigger.dataset.health = health;
588
+ }
589
+ const label = instance?.container?.querySelector('[data-diagnostics-health-label]');
590
+ if (label) {
591
+ label.textContent = t(instance, {
592
+ ok: 'diagnosticsPillOk',
593
+ warn: 'diagnosticsPillWarn',
594
+ fail: 'diagnosticsPillFail'
595
+ }[health] || 'diagnosticsPillUnknown');
491
596
  }
492
597
  }
493
598