codex-overleaf-link 2.1.5 → 2.2.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.
Files changed (66) hide show
  1. package/README.md +27 -23
  2. package/extension/bootstrap/background.js +14 -1
  3. package/extension/bootstrap/manifest.template.json +1 -1
  4. package/extension/runtime-manifest.json +10 -0
  5. package/extension/src/background.js +507 -8
  6. package/extension/src/backgroundUpdateCoordinator.js +284 -19
  7. package/extension/src/content/activeTurnControl.js +179 -0
  8. package/extension/src/content/composerPanel.js +14 -5
  9. package/extension/src/content/contentRuntime.js +330 -309
  10. package/extension/src/content/diagnosticsPanel.js +132 -1
  11. package/extension/src/content/markdownDomRenderer.js +451 -0
  12. package/extension/src/content/markdownText.js +86 -7
  13. package/extension/src/content/mathText.js +49 -4
  14. package/extension/src/content/modelPicker.js +14 -5
  15. package/extension/src/content/nativeChannel.js +7 -1
  16. package/extension/src/content/panelRenderer.js +112 -12
  17. package/extension/src/content/pendingInputView.js +106 -0
  18. package/extension/src/content/projectProviderSelection.js +68 -0
  19. package/extension/src/content/projectSessionCleanup.js +4 -0
  20. package/extension/src/content/providerSettingsCoordinator.js +170 -22
  21. package/extension/src/content/providerSettingsDialog.js +2 -2
  22. package/extension/src/content/recentProjects.js +7 -2
  23. package/extension/src/content/runGuidanceController.js +70 -0
  24. package/extension/src/content/runGuidanceView.js +48 -0
  25. package/extension/src/content/runQueueScheduler.js +260 -0
  26. package/extension/src/content/runTimelineView.js +33 -80
  27. package/extension/src/content/sessionManager.js +2 -2
  28. package/extension/src/content/sessionPersistence.js +62 -0
  29. package/extension/src/content/settingsPanel.js +1 -1
  30. package/extension/src/content/updateNotice.js +80 -1
  31. package/extension/src/page/writebackRouter.js +3 -9
  32. package/extension/src/shared/compatibility.js +2 -1
  33. package/extension/src/shared/i18n.js +38 -0
  34. package/extension/src/shared/providerProfiles.js +3 -2
  35. package/extension/src/shared/runInputQueue.js +253 -0
  36. package/extension/src/shared/sessionState.js +45 -22
  37. package/extension/src/shared/storageDb.js +39 -44
  38. package/extension/src/shared/storageMigration.js +123 -3
  39. package/extension/src/shared/storageRunActions.js +34 -1
  40. package/extension/src/shared/updateConsent.js +15 -4
  41. package/extension/styles/panel.css +319 -20
  42. package/extension/vendor/katex/katex.min.css +1 -1
  43. package/extension/vendor/markdown-it/LICENSE +22 -0
  44. package/extension/vendor/markdown-it/SOURCE.json +7 -0
  45. package/extension/vendor/markdown-it/VERSION +1 -0
  46. package/extension/vendor/markdown-it/markdown-it.min.js +3 -0
  47. package/native-host/src/anthropicBridgeRequest.js +3 -3
  48. package/native-host/src/anthropicBridgeResponse.js +58 -17
  49. package/native-host/src/anthropicMessagesBridge.js +156 -23
  50. package/native-host/src/chatBridgeRequest.js +1 -1
  51. package/native-host/src/chatBridgeResponse.js +12 -8
  52. package/native-host/src/chatCompletionsBridge.js +22 -40
  53. package/native-host/src/codexPromptAssembly.js +3 -1
  54. package/native-host/src/codexProviderLaunch.js +6 -3
  55. package/native-host/src/codexSessionRunner.js +65 -65
  56. package/native-host/src/codexSessionTiming.js +45 -0
  57. package/native-host/src/index.js +58 -3
  58. package/native-host/src/managedInstall.js +45 -7
  59. package/native-host/src/providerProfile.js +2 -2
  60. package/native-host/src/providerStreamLifecycle.js +100 -0
  61. package/native-host/src/responsesPassthroughBridge.js +636 -0
  62. package/native-host/src/taskRunnerRuntime.js +81 -2
  63. package/native-host/src/updateArchive.js +4 -3
  64. package/native-host/src/updateManager.js +306 -19
  65. package/native-host/src/updateTrust.js +1 -1
  66. package/package.json +3 -1
@@ -8,6 +8,9 @@
8
8
  'use strict';
9
9
 
10
10
  var PREFS_KEY = 'codexOverleafPrefs';
11
+ var SESSION_TOMBSTONES_KEY = 'codexOverleafSessionTombstones';
12
+ var SESSION_TOMBSTONE_ENTRY_PREFIX = 'codexOverleafSessionTombstone:v2:';
13
+ var MAX_DELETED_SESSION_IDS_PER_PROJECT = 100;
11
14
  var CUSTOM_INSTRUCTIONS_MAX_CHARS = 12000;
12
15
  var PROJECT_PREF_KEY_MAX_CHARS = 160;
13
16
 
@@ -15,15 +18,20 @@
15
18
  var StorageDb = (typeof window !== 'undefined' && window.CodexOverleafStorageDb)
16
19
  ? window.CodexOverleafStorageDb
17
20
  : require('./storageDb');
18
- return chrome.storage.local.get([PREFS_KEY, legacyStorageKey]).then(function (stored) {
21
+ return chrome.storage.local.get(null).then(function (stored) {
19
22
  var prefs = normalizePrefs(stored[PREFS_KEY] || {});
23
+ var tombstones = collectSessionTombstones(stored);
24
+ var deletedSessionIds = getDeletedSessionIds(tombstones, projectId);
20
25
  var schemaVersion = prefs.storageSchemaVersion || 0;
21
26
 
22
27
  if (schemaVersion >= StorageDb.TARGET_SCHEMA_VERSION) {
23
28
  var activeSessionByProject = prefs.activeSessionByProject || {};
24
29
  var activeSessionId = activeSessionByProject[projectId] || '';
25
30
  return StorageDb.getAllByIndex('sessions', 'projectId', projectId).then(function (sessions) {
26
- return { prefs: prefs, sessions: sessions, activeSessionId: activeSessionId, migrated: false };
31
+ var visibleSessions = sessions.filter(function (session) {
32
+ return deletedSessionIds.indexOf(session && session.id) === -1;
33
+ });
34
+ return { prefs: prefs, sessions: visibleSessions, activeSessionId: activeSessionId, migrated: false };
27
35
  });
28
36
  }
29
37
 
@@ -35,6 +43,7 @@
35
43
  for (var i = 0; i < legacySessions.length; i++) {
36
44
  var legacy = legacySessions[i];
37
45
  if (!legacy || !legacy.id) { continue; }
46
+ if (deletedSessionIds.indexOf(legacy.id) !== -1) { continue; }
38
47
  var record = StorageDb.buildSessionRecord(
39
48
  buildLegacySessionRecordInput(projectId, legacyBlob, legacy)
40
49
  );
@@ -101,6 +110,112 @@
101
110
  });
102
111
  }
103
112
 
113
+ function normalizeDeletedSessionIdsByProject(value) {
114
+ var result = {};
115
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
116
+ return result;
117
+ }
118
+ Object.keys(value).forEach(function (rawProjectId) {
119
+ var projectId = normalizeProjectPrefKey(rawProjectId);
120
+ if (!projectId || !Array.isArray(value[rawProjectId])) {
121
+ return;
122
+ }
123
+ var seen = {};
124
+ var ids = value[rawProjectId].map(function (id) {
125
+ return normalizeTextField(id, PROJECT_PREF_KEY_MAX_CHARS);
126
+ }).filter(function (id) {
127
+ if (!id || seen[id]) { return false; }
128
+ seen[id] = true;
129
+ return true;
130
+ }).slice(-MAX_DELETED_SESSION_IDS_PER_PROJECT);
131
+ if (ids.length) {
132
+ result[projectId] = ids;
133
+ }
134
+ });
135
+ return result;
136
+ }
137
+
138
+ function getDeletedSessionIds(tombstones, projectId) {
139
+ var normalized = normalizeDeletedSessionIdsByProject(tombstones);
140
+ var key = normalizeProjectPrefKey(projectId);
141
+ return key && Array.isArray(normalized[key]) ? normalized[key].slice() : [];
142
+ }
143
+
144
+ function loadSessionTombstones() {
145
+ return chrome.storage.local.get(null).then(function (stored) {
146
+ return collectSessionTombstones(stored);
147
+ });
148
+ }
149
+
150
+ function addSessionTombstones(projectId, sessionIds) {
151
+ var key = normalizeProjectPrefKey(projectId);
152
+ if (!key) {
153
+ return loadSessionTombstones();
154
+ }
155
+ var incoming = (Array.isArray(sessionIds) ? sessionIds : [])
156
+ .map(function (id) { return normalizeTextField(id, PROJECT_PREF_KEY_MAX_CHARS); })
157
+ .filter(Boolean);
158
+ if (!incoming.length) {
159
+ return loadSessionTombstones();
160
+ }
161
+ var deletedAt = new Date().toISOString();
162
+ var payload = {};
163
+ incoming.forEach(function (sessionId) {
164
+ payload[buildSessionTombstoneEntryKey(key, sessionId)] = {
165
+ projectId: key,
166
+ sessionId: sessionId,
167
+ deletedAt: deletedAt
168
+ };
169
+ });
170
+ return chrome.storage.local.set(payload)
171
+ .then(function () { return pruneSessionTombstoneEntries(key); })
172
+ .then(loadSessionTombstones);
173
+ }
174
+
175
+ function collectSessionTombstones(stored) {
176
+ var tombstones = normalizeDeletedSessionIdsByProject(
177
+ stored && stored[SESSION_TOMBSTONES_KEY] || {}
178
+ );
179
+ Object.keys(stored || {}).forEach(function (storageKey) {
180
+ if (storageKey.indexOf(SESSION_TOMBSTONE_ENTRY_PREFIX) !== 0) {
181
+ return;
182
+ }
183
+ var entry = stored[storageKey];
184
+ var projectId = normalizeProjectPrefKey(entry && entry.projectId);
185
+ var sessionId = normalizeTextField(entry && entry.sessionId, PROJECT_PREF_KEY_MAX_CHARS);
186
+ if (!projectId || !sessionId) {
187
+ return;
188
+ }
189
+ tombstones[projectId] = (tombstones[projectId] || [])
190
+ .filter(function (id) { return id !== sessionId; })
191
+ .concat(sessionId)
192
+ .slice(-MAX_DELETED_SESSION_IDS_PER_PROJECT);
193
+ });
194
+ return normalizeDeletedSessionIdsByProject(tombstones);
195
+ }
196
+
197
+ function buildSessionTombstoneEntryKey(projectId, sessionId) {
198
+ return SESSION_TOMBSTONE_ENTRY_PREFIX +
199
+ encodeURIComponent(projectId) + ':' +
200
+ encodeURIComponent(sessionId);
201
+ }
202
+
203
+ function pruneSessionTombstoneEntries(projectId) {
204
+ return chrome.storage.local.get(null).then(function (stored) {
205
+ var entries = Object.keys(stored || {}).filter(function (storageKey) {
206
+ var entry = stored[storageKey];
207
+ return storageKey.indexOf(SESSION_TOMBSTONE_ENTRY_PREFIX) === 0 &&
208
+ normalizeProjectPrefKey(entry && entry.projectId) === projectId;
209
+ }).sort(function (leftKey, rightKey) {
210
+ var left = String(stored[leftKey] && stored[leftKey].deletedAt || '');
211
+ var right = String(stored[rightKey] && stored[rightKey].deletedAt || '');
212
+ return left === right ? leftKey.localeCompare(rightKey) : left.localeCompare(right);
213
+ });
214
+ var obsolete = entries.slice(0, Math.max(0, entries.length - MAX_DELETED_SESSION_IDS_PER_PROJECT));
215
+ return obsolete.length ? chrome.storage.local.remove(obsolete) : undefined;
216
+ });
217
+ }
218
+
104
219
  function normalizePrefs(prefs) {
105
220
  var source = prefs && typeof prefs === 'object' ? prefs : {};
106
221
  return Object.assign({}, source, {
@@ -162,8 +277,13 @@
162
277
 
163
278
  return {
164
279
  PREFS_KEY: PREFS_KEY,
280
+ SESSION_TOMBSTONES_KEY: SESSION_TOMBSTONES_KEY,
165
281
  runMigrationIfNeeded: runMigrationIfNeeded,
166
282
  savePrefs: savePrefs,
167
- loadPrefs: loadPrefs
283
+ loadPrefs: loadPrefs,
284
+ loadSessionTombstones: loadSessionTombstones,
285
+ addSessionTombstones: addSessionTombstones,
286
+ getDeletedSessionIds: getDeletedSessionIds,
287
+ normalizeDeletedSessionIdsByProject: normalizeDeletedSessionIdsByProject
168
288
  };
169
289
  });
@@ -101,9 +101,42 @@
101
101
  };
102
102
  }
103
103
 
104
+ function compactStructuredEventValue(value, options, depth) {
105
+ var config = options || {};
106
+ var d = depth || 0;
107
+ if (typeof value === 'string') {
108
+ return typeof config.normalizeString === 'function' ? config.normalizeString(value) : value;
109
+ }
110
+ if (value === null || typeof value === 'number' || typeof value === 'boolean') return value;
111
+ if (d > 6 || typeof value !== 'object') return null;
112
+ if (Array.isArray(value)) {
113
+ return value.slice(0, 32).map(function (item) {
114
+ return compactStructuredEventValue(item, config, d + 1);
115
+ });
116
+ }
117
+ var out = {};
118
+ var keys = Object.keys(value).slice(0, 32);
119
+ for (var i = 0; i < keys.length; i++) {
120
+ out[keys[i]] = compactStructuredEventValue(value[keys[i]], config, d + 1);
121
+ }
122
+ return out;
123
+ }
124
+
125
+ function hashString(value) {
126
+ var hash = 2166136261;
127
+ var text = String(value || '');
128
+ for (var i = 0; i < text.length; i++) {
129
+ hash ^= text.charCodeAt(i);
130
+ hash = Math.imul(hash, 16777619);
131
+ }
132
+ return (hash >>> 0).toString(16).padStart(8, '0');
133
+ }
134
+
104
135
  return {
136
+ compactStructuredEventValue: compactStructuredEventValue,
105
137
  compactRunsForStorage: compactRunsForStorage,
106
138
  compactRunActionPayload: compactRunActionPayload,
107
- compactProviderSnapshot: compactProviderSnapshot
139
+ compactProviderSnapshot: compactProviderSnapshot,
140
+ hashString: hashString
108
141
  };
109
142
  });
@@ -18,6 +18,7 @@
18
18
  'waiting_for_idle',
19
19
  'applying',
20
20
  'awaiting_health',
21
+ 'rolling_back',
21
22
  'committed',
22
23
  'rolled_back',
23
24
  'failed'
@@ -27,7 +28,8 @@
27
28
  'staged',
28
29
  'waiting_for_idle',
29
30
  'applying',
30
- 'awaiting_health'
31
+ 'awaiting_health',
32
+ 'rolling_back'
31
33
  ]);
32
34
  const TERMINAL_STATES = new Set(['committed', 'rolled_back', 'failed']);
33
35
  const QUIET_FAILURE_CODES = new Set([
@@ -44,6 +46,7 @@
44
46
  waiting_for_idle: { value: 65, determinate: true, phase: 'waiting' },
45
47
  applying: { value: 82, determinate: false, phase: 'applying' },
46
48
  awaiting_health: { value: 94, determinate: false, phase: 'health' },
49
+ rolling_back: { value: 94, determinate: false, phase: 'rollback' },
47
50
  committed: { value: 100, determinate: true, phase: 'committed' },
48
51
  rolled_back: { value: 94, determinate: true, phase: 'rolled_back' },
49
52
  failed: { value: 0, determinate: true, phase: 'failed' }
@@ -63,8 +66,12 @@
63
66
  blocker: blockers[0] || '',
64
67
  blockers,
65
68
  transactionId: safeId(value.transactionId),
69
+ initiatedBy: ['automatic', 'manual'].includes(value.initiatedBy) ? value.initiatedBy : '',
66
70
  lastCheckedAt: finiteNumber(value.lastCheckedAt),
67
71
  stagedAt: finiteNumber(value.stagedAt),
72
+ phaseStartedAt: finiteNumber(value.phaseStartedAt),
73
+ deadlineAt: finiteNumber(value.deadlineAt),
74
+ heartbeatAt: finiteNumber(value.heartbeatAt),
68
75
  postponeUntil: finiteNumber(value.postponeUntil),
69
76
  code: safeToken(value.code),
70
77
  message: String(value.message || '').replace(/\s+/g, ' ').trim().slice(0, 300)
@@ -96,7 +103,11 @@
96
103
  const execution = EXECUTION_STATES.has(state.state);
97
104
  const available = state.state === 'update_available' && newer;
98
105
  const progress = getProgressModel(state);
99
- const quietFailure = state.state === 'failed' && QUIET_FAILURE_CODES.has(state.code);
106
+ const quietFailure = state.state === 'failed' &&
107
+ state.initiatedBy !== 'manual' &&
108
+ QUIET_FAILURE_CODES.has(state.code);
109
+ const visibleFailure = state.state === 'failed' &&
110
+ (state.initiatedBy === 'manual' || (!quietFailure && newer));
100
111
 
101
112
  return {
102
113
  state,
@@ -112,7 +123,7 @@
112
123
  snoozed,
113
124
  execution,
114
125
  showPanel: (available && !snoozed) || execution || state.state === 'rolled_back' ||
115
- (state.state === 'failed' && !quietFailure && newer),
126
+ visibleFailure,
116
127
  badge: getBadge(state, { available, snoozed }),
117
128
  actions: {
118
129
  check: ['idle', 'committed', 'rolled_back', 'failed'].includes(state.state),
@@ -135,7 +146,7 @@
135
146
  }
136
147
 
137
148
  function getBadge(state, flags) {
138
- if (state.state === 'applying' || state.state === 'awaiting_health') {
149
+ if (state.state === 'applying' || state.state === 'awaiting_health' || state.state === 'rolling_back') {
139
150
  return { text: '...', color: '#3578bd' };
140
151
  }
141
152
  if (state.state === 'failed' || state.state === 'rolled_back') {
@@ -2,6 +2,136 @@
2
2
  --codex-overleaf-panel-width: 380px;
3
3
  }
4
4
 
5
+ /* Rich response geometry is shared by streaming and settled output. Repeated
6
+ class selectors intentionally outrank older component-local declarations. */
7
+ #codex-overleaf-panel .run-stream-text.run-stream-text,
8
+ #codex-overleaf-panel .run-final-answer.run-final-answer {
9
+ min-width: 0;
10
+ max-width: 100%;
11
+ color: var(--tl-fg-2);
12
+ font-size: 14px;
13
+ line-height: 1.6;
14
+ overflow-wrap: anywhere;
15
+ word-break: normal;
16
+ }
17
+
18
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) > :first-child {
19
+ margin-top: 0;
20
+ }
21
+
22
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) > :last-child {
23
+ margin-bottom: 0;
24
+ }
25
+
26
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) p {
27
+ margin: 0.58em 0;
28
+ }
29
+
30
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) :is(h1, h2, h3, h4, h5, h6) {
31
+ margin: 1.05em 0 0.45em;
32
+ color: var(--tl-fg-1);
33
+ font-weight: 720;
34
+ line-height: 1.3;
35
+ }
36
+
37
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) h1 { font-size: 1.35em; }
38
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) h2 { font-size: 1.22em; }
39
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) h3 { font-size: 1.12em; }
40
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) :is(h4, h5, h6) { font-size: 1em; }
41
+
42
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) :is(ul, ol) {
43
+ margin: 0.55em 0;
44
+ padding-inline-start: 1.55em;
45
+ }
46
+
47
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) :is(ul, ol) :is(ul, ol) {
48
+ margin: 0.2em 0;
49
+ }
50
+
51
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) li {
52
+ margin: 0.2em 0;
53
+ }
54
+
55
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) .run-markdown-quote {
56
+ margin: 0.7em 0;
57
+ padding: 0.12em 0 0.12em 0.9em;
58
+ border-inline-start: 3px solid var(--tl-accent, #79b8f2);
59
+ color: var(--tl-fg-3);
60
+ }
61
+
62
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) .run-markdown-table {
63
+ width: 100%;
64
+ margin: 0.75em 0;
65
+ border-collapse: collapse;
66
+ font-size: 0.94em;
67
+ }
68
+
69
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) .run-markdown-table :is(th, td) {
70
+ padding: 0.42em 0.58em;
71
+ border: 1px solid var(--tl-border);
72
+ text-align: start;
73
+ vertical-align: top;
74
+ }
75
+
76
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) .run-markdown-table th {
77
+ background: var(--tl-surface-2);
78
+ color: var(--tl-fg-1);
79
+ font-weight: 700;
80
+ }
81
+
82
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) .is-align-center { text-align: center; }
83
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) .is-align-right { text-align: right; }
84
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) .is-align-left { text-align: left; }
85
+
86
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) hr {
87
+ margin: 1em 0;
88
+ border: 0;
89
+ border-top: 1px solid var(--tl-border);
90
+ }
91
+
92
+ #codex-overleaf-panel .run-math--display.run-math--display {
93
+ display: block;
94
+ max-width: 100%;
95
+ margin: 14px 0;
96
+ padding: 2px 0 5px;
97
+ overflow-x: auto;
98
+ overflow-y: hidden;
99
+ scrollbar-width: thin;
100
+ }
101
+
102
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) .katex-display {
103
+ margin: 0;
104
+ }
105
+
106
+ #codex-overleaf-panel :is(.run-stream-text, .run-final-answer) .katex .text.text {
107
+ font-family: KaTeX_Main, "Times New Roman", serif !important;
108
+ }
109
+
110
+ #codex-overleaf-panel .codex-custom-instructions-panel .codex-custom-instructions-head {
111
+ display: grid;
112
+ grid-template-columns: 24px minmax(0, 1fr);
113
+ gap: 10px;
114
+ align-items: start;
115
+ justify-content: initial;
116
+ }
117
+
118
+ #codex-overleaf-panel .codex-custom-instructions-panel .codex-custom-instructions-head > div {
119
+ min-width: 0;
120
+ }
121
+
122
+ #codex-overleaf-panel .codex-project-settings-panel .codex-provider-settings-entry {
123
+ display: grid;
124
+ grid-template-columns: minmax(0, 1fr);
125
+ gap: 12px;
126
+ align-items: stretch;
127
+ }
128
+
129
+ #codex-overleaf-panel .codex-project-settings-panel .codex-provider-settings-entry .codex-set-btn,
130
+ #codex-overleaf-panel .codex-project-settings-panel [data-update-settings] button {
131
+ width: 100%;
132
+ justify-content: center;
133
+ }
134
+
5
135
  /* v2.1 provider profiles: detailed configuration lives in a viewport modal. */
6
136
  .codex-provider-settings-entry {
7
137
  display: flex;
@@ -2181,17 +2311,40 @@
2181
2311
  min-width: 0;
2182
2312
  }
2183
2313
 
2184
- #codex-overleaf-panel .run-prompt {
2314
+ #codex-overleaf-panel .run-prompt,
2315
+ #codex-overleaf-panel .run-guidance-message {
2185
2316
  box-sizing: border-box;
2317
+ width: fit-content;
2318
+ max-width: 100%;
2319
+ margin-left: auto;
2186
2320
  border: 1px solid var(--tl-border-strong);
2187
2321
  border-radius: 8px;
2188
2322
  background: var(--tl-surface-1);
2189
2323
  color: var(--tl-fg-1);
2190
2324
  padding: 7px 9px;
2191
2325
  white-space: pre-wrap;
2326
+ overflow-wrap: anywhere;
2192
2327
  word-break: break-word;
2193
2328
  }
2194
2329
 
2330
+ #codex-overleaf-panel .run-guidance-list:empty {
2331
+ display: none;
2332
+ }
2333
+
2334
+ #codex-overleaf-panel .run-guidance-message {
2335
+ display: block;
2336
+ border-top: 2px solid var(--tl-accent, #55b9f3);
2337
+ margin: 7px 0 4px auto;
2338
+ animation: tl-slide-in 140ms ease-out;
2339
+ }
2340
+
2341
+ #codex-overleaf-panel .run-guidance-text {
2342
+ min-width: 0;
2343
+ color: var(--tl-fg-1);
2344
+ white-space: pre-wrap;
2345
+ overflow-wrap: anywhere;
2346
+ }
2347
+
2195
2348
  #codex-overleaf-panel .run-turn-meta {
2196
2349
  display: flex;
2197
2350
  align-items: center;
@@ -2301,6 +2454,12 @@
2301
2454
  margin-top: 2px;
2302
2455
  }
2303
2456
 
2457
+ /* The process disclosure owns machine activity. User Guidance messages live
2458
+ beside the prompt, outside this collapsible activity region. */
2459
+ #codex-overleaf-panel .run-process:not([open]) + .run-activity-list {
2460
+ display: none;
2461
+ }
2462
+
2304
2463
  #codex-overleaf-panel .run-activity {
2305
2464
  display: grid;
2306
2465
  grid-template-columns: 14px minmax(0, 1fr);
@@ -2475,30 +2634,55 @@
2475
2634
  }
2476
2635
 
2477
2636
  #codex-overleaf-panel .run-math {
2478
- max-width: 100%;
2479
2637
  color: inherit;
2480
- font-size: 1.02em;
2638
+ font-size: 1em;
2481
2639
  }
2482
2640
 
2483
2641
  #codex-overleaf-panel .run-math--inline {
2484
- display: inline-block;
2485
- overflow-x: auto;
2486
- overflow-y: hidden;
2487
- vertical-align: -0.15em;
2642
+ display: inline;
2643
+ max-width: none;
2644
+ overflow: visible;
2645
+ vertical-align: baseline;
2646
+ white-space: nowrap;
2647
+ }
2648
+
2649
+ #codex-overleaf-panel .run-math--inline .katex {
2650
+ display: inline;
2651
+ overflow-wrap: normal;
2652
+ word-break: normal;
2653
+ white-space: nowrap;
2488
2654
  }
2489
2655
 
2490
2656
  #codex-overleaf-panel .run-math--display {
2657
+ box-sizing: border-box;
2491
2658
  display: block;
2659
+ width: 100%;
2660
+ max-width: 100%;
2492
2661
  overflow-x: auto;
2493
2662
  overflow-y: hidden;
2494
- margin: 8px 0;
2495
- padding: 2px 0 4px;
2663
+ margin: 10px 0;
2664
+ padding: 4px 2px 7px;
2665
+ overscroll-behavior-inline: contain;
2666
+ scrollbar-width: thin;
2496
2667
  }
2497
2668
 
2498
2669
  #codex-overleaf-panel .run-math--display .katex-display {
2499
- min-width: max-content;
2670
+ box-sizing: border-box;
2671
+ width: max-content;
2672
+ min-width: 100%;
2500
2673
  margin: 0;
2501
- text-align: left;
2674
+ text-align: center;
2675
+ }
2676
+
2677
+ #codex-overleaf-panel .run-math .katex {
2678
+ overflow-wrap: normal;
2679
+ word-break: normal;
2680
+ }
2681
+
2682
+ #codex-overleaf-panel .run-math .katex .text,
2683
+ #codex-overleaf-panel .run-math .katex .text * {
2684
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
2685
+ font-size: 0.94em;
2502
2686
  }
2503
2687
 
2504
2688
  #codex-overleaf-panel .run-math--fallback {
@@ -3498,21 +3682,16 @@
3498
3682
  transition: background 120ms ease, filter 120ms ease;
3499
3683
  }
3500
3684
 
3501
- #codex-overleaf-panel .codex-composer-toolbar [data-run]:hover {
3502
- filter: brightness(1.1);
3503
- }
3504
-
3505
- #codex-overleaf-panel[data-running="true"] .codex-composer-toolbar [data-run] {
3685
+ #codex-overleaf-panel .codex-composer-toolbar [data-run][data-action="cancel"] {
3506
3686
  color: transparent;
3507
3687
  }
3508
3688
 
3509
- /* While running, the button is the cancel control — hovering signals "stop". */
3510
- #codex-overleaf-panel[data-running="true"] .codex-composer-toolbar [data-run]:hover {
3689
+ #codex-overleaf-panel .codex-composer-toolbar [data-run][data-action="cancel"]:hover {
3511
3690
  background: var(--tl-fail);
3512
3691
  filter: none;
3513
3692
  }
3514
3693
 
3515
- #codex-overleaf-panel[data-running="true"] .codex-composer-toolbar [data-run]::after {
3694
+ #codex-overleaf-panel .codex-composer-toolbar [data-run][data-action="cancel"]::after {
3516
3695
  content: "";
3517
3696
  position: absolute;
3518
3697
  top: 50%;
@@ -3523,8 +3702,12 @@
3523
3702
  border: 2px solid rgba(255, 255, 255, 0.35);
3524
3703
  border-top-color: #ffffff;
3525
3704
  border-radius: 50%;
3526
- animation: codex-run-spin 800ms linear infinite;
3527
3705
  transform: translate(-50%, -50%);
3706
+ animation: codex-run-spin 800ms linear infinite;
3707
+ }
3708
+
3709
+ #codex-overleaf-panel .codex-composer-toolbar [data-run]:hover {
3710
+ filter: brightness(1.1);
3528
3711
  }
3529
3712
 
3530
3713
  @keyframes codex-run-spin {
@@ -3533,6 +3716,106 @@
3533
3716
  }
3534
3717
  }
3535
3718
 
3719
+ #codex-overleaf-panel .codex-pending-inputs {
3720
+ display: grid;
3721
+ gap: 6px;
3722
+ padding: 0 6px 7px;
3723
+ }
3724
+
3725
+ #codex-overleaf-panel .codex-pending-inputs[hidden] {
3726
+ display: none;
3727
+ }
3728
+
3729
+ #codex-overleaf-panel .codex-pending-input {
3730
+ display: grid;
3731
+ grid-template-columns: minmax(0, 1fr) auto;
3732
+ align-items: center;
3733
+ gap: 8px;
3734
+ min-width: 0;
3735
+ padding: 8px 9px;
3736
+ border: 1px solid var(--tl-border);
3737
+ border-radius: 9px;
3738
+ background: color-mix(in srgb, var(--tl-surface-1) 86%, var(--tl-accent) 14%);
3739
+ }
3740
+
3741
+ #codex-overleaf-panel .codex-pending-input[data-status="paused"] {
3742
+ background: color-mix(in srgb, var(--tl-surface-1) 90%, var(--tl-warn) 10%);
3743
+ }
3744
+
3745
+ #codex-overleaf-panel .codex-pending-input-copy {
3746
+ display: grid;
3747
+ min-width: 0;
3748
+ gap: 2px;
3749
+ }
3750
+
3751
+ #codex-overleaf-panel .codex-pending-input-status {
3752
+ color: var(--tl-fg-3);
3753
+ font-size: 10px;
3754
+ font-weight: 700;
3755
+ letter-spacing: 0.06em;
3756
+ text-transform: uppercase;
3757
+ }
3758
+
3759
+ #codex-overleaf-panel .codex-pending-input-text {
3760
+ color: var(--tl-fg-1);
3761
+ font-size: 12px;
3762
+ line-height: 1.35;
3763
+ overflow-wrap: anywhere;
3764
+ white-space: pre-wrap;
3765
+ }
3766
+
3767
+ #codex-overleaf-panel .codex-pending-input-actions {
3768
+ display: inline-flex;
3769
+ gap: 4px;
3770
+ }
3771
+
3772
+ #codex-overleaf-panel .codex-pending-input-actions button {
3773
+ min-height: 24px;
3774
+ padding: 0 8px;
3775
+ border-radius: 6px;
3776
+ color: var(--tl-fg-2);
3777
+ background: var(--tl-surface-2);
3778
+ font-size: 11px;
3779
+ }
3780
+
3781
+ #codex-overleaf-panel .codex-pending-input-actions button:hover {
3782
+ color: var(--tl-fg-1);
3783
+ background: var(--tl-hover);
3784
+ }
3785
+
3786
+ #codex-overleaf-panel .codex-pending-input-actions button:disabled {
3787
+ opacity: 0.45;
3788
+ }
3789
+
3790
+ #codex-overleaf-panel .codex-pending-input-actions .codex-pending-input-icon {
3791
+ display: inline-grid;
3792
+ place-items: center;
3793
+ width: 26px;
3794
+ min-width: 26px;
3795
+ min-height: 26px;
3796
+ padding: 0;
3797
+ border-color: transparent;
3798
+ background: transparent;
3799
+ }
3800
+
3801
+ #codex-overleaf-panel .codex-pending-input-icon svg {
3802
+ width: 16px;
3803
+ height: 16px;
3804
+ fill: none;
3805
+ stroke: currentColor;
3806
+ stroke-width: 1.6;
3807
+ stroke-linecap: round;
3808
+ stroke-linejoin: round;
3809
+ }
3810
+
3811
+ #codex-overleaf-panel .codex-pending-input-icon[data-action="guide"]:hover {
3812
+ color: var(--tl-accent);
3813
+ }
3814
+
3815
+ #codex-overleaf-panel .codex-pending-input-icon[data-action="remove"]:hover {
3816
+ color: var(--tl-fail);
3817
+ }
3818
+
3536
3819
  #codex-overleaf-panel .codex-composer-toolbar [data-add-context][data-active="true"],
3537
3820
  #codex-overleaf-panel .codex-composer-toolbar [data-add-context][data-has-focus="true"] {
3538
3821
  background: var(--tl-hover);
@@ -4739,6 +5022,22 @@
4739
5022
  text-overflow: ellipsis;
4740
5023
  }
4741
5024
 
5025
+ #codex-overleaf-panel .codex-update-notice-recovery {
5026
+ margin-top: 5px;
5027
+ color: var(--tl-fg-2, #d5dad6);
5028
+ font-size: 10.5px;
5029
+ font-weight: 700;
5030
+ }
5031
+
5032
+ #codex-overleaf-panel .codex-update-notice-command {
5033
+ display: block;
5034
+ max-width: 100%;
5035
+ overflow-wrap: anywhere;
5036
+ color: #c5d9ec;
5037
+ font: 10px/1.45 ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
5038
+ user-select: text;
5039
+ }
5040
+
4742
5041
  #codex-overleaf-panel .codex-update-notice-actions {
4743
5042
  display: flex;
4744
5043
  gap: 6px;