jupyterlab-codex-sidebar 0.1.4 → 0.1.6

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 (153) hide show
  1. package/.claude/settings.local.json +9 -0
  2. package/.github/workflows/unit-tests.yml +27 -0
  3. package/.jupyterlab-playwright.log +0 -0
  4. package/README.md +83 -9
  5. package/docs/images/codex-sidebar-screenshot.png +0 -0
  6. package/jupyterlab_codex/handlers.py +938 -297
  7. package/jupyterlab_codex/labextension/package.json +13 -3
  8. package/jupyterlab_codex/labextension/static/525.224526d045c727069de6.js +2 -0
  9. package/jupyterlab_codex/labextension/static/737.e7de3ad9dd6ded798340.js +1 -0
  10. package/jupyterlab_codex/labextension/static/remoteEntry.6ef5e7167763a316c000.js +1 -0
  11. package/jupyterlab_codex/protocol.py +297 -0
  12. package/jupyterlab_codex/runner.py +58 -15
  13. package/jupyterlab_codex/sessions.py +582 -97
  14. package/lib/codexChat.d.ts +13 -0
  15. package/lib/codexChat.js +2506 -0
  16. package/lib/codexChat.js.map +1 -0
  17. package/lib/codexChatAttachmentDedup.d.ts +10 -0
  18. package/lib/codexChatAttachmentDedup.js +35 -0
  19. package/lib/codexChatAttachmentDedup.js.map +1 -0
  20. package/lib/codexChatAttachmentLimit.d.ts +18 -0
  21. package/lib/codexChatAttachmentLimit.js +50 -0
  22. package/lib/codexChatAttachmentLimit.js.map +1 -0
  23. package/lib/codexChatAttachmentState.d.ts +15 -0
  24. package/lib/codexChatAttachmentState.js +16 -0
  25. package/lib/codexChatAttachmentState.js.map +1 -0
  26. package/lib/codexChatDocumentUtils.d.ts +70 -0
  27. package/lib/codexChatDocumentUtils.js +506 -0
  28. package/lib/codexChatDocumentUtils.js.map +1 -0
  29. package/lib/codexChatFormatting.d.ts +11 -0
  30. package/lib/codexChatFormatting.js +83 -0
  31. package/lib/codexChatFormatting.js.map +1 -0
  32. package/lib/codexChatNotice.d.ts +3 -0
  33. package/lib/codexChatNotice.js +74 -0
  34. package/lib/codexChatNotice.js.map +1 -0
  35. package/lib/codexChatPersistence.d.ts +35 -0
  36. package/lib/codexChatPersistence.js +158 -0
  37. package/lib/codexChatPersistence.js.map +1 -0
  38. package/lib/codexChatPrimitives.d.ts +44 -0
  39. package/lib/codexChatPrimitives.js +156 -0
  40. package/lib/codexChatPrimitives.js.map +1 -0
  41. package/lib/codexChatRender.d.ts +24 -0
  42. package/lib/codexChatRender.js +293 -0
  43. package/lib/codexChatRender.js.map +1 -0
  44. package/lib/codexChatSessionFactory.d.ts +15 -0
  45. package/lib/codexChatSessionFactory.js +45 -0
  46. package/lib/codexChatSessionFactory.js.map +1 -0
  47. package/lib/codexChatSessionKey.d.ts +3 -0
  48. package/lib/codexChatSessionKey.js +14 -0
  49. package/lib/codexChatSessionKey.js.map +1 -0
  50. package/lib/codexChatStorage.d.ts +4 -0
  51. package/lib/codexChatStorage.js +37 -0
  52. package/lib/codexChatStorage.js.map +1 -0
  53. package/lib/codexSessionResolver.d.ts +12 -0
  54. package/lib/codexSessionResolver.js +38 -0
  55. package/lib/codexSessionResolver.js.map +1 -0
  56. package/lib/handlers/activitySummarizer.d.ts +15 -0
  57. package/lib/handlers/activitySummarizer.js +327 -0
  58. package/lib/handlers/activitySummarizer.js.map +1 -0
  59. package/lib/handlers/codexMessageTypes.d.ts +30 -0
  60. package/lib/handlers/codexMessageTypes.js +2 -0
  61. package/lib/handlers/codexMessageTypes.js.map +1 -0
  62. package/lib/handlers/codexMessageUtils.d.ts +46 -0
  63. package/lib/handlers/codexMessageUtils.js +144 -0
  64. package/lib/handlers/codexMessageUtils.js.map +1 -0
  65. package/lib/handlers/handleCodexSocketMessage.d.ts +107 -0
  66. package/lib/handlers/handleCodexSocketMessage.js +78 -0
  67. package/lib/handlers/handleCodexSocketMessage.js.map +1 -0
  68. package/lib/handlers/sessionSyncHandler.d.ts +34 -0
  69. package/lib/handlers/sessionSyncHandler.js +181 -0
  70. package/lib/handlers/sessionSyncHandler.js.map +1 -0
  71. package/lib/hooks/useCodexSocket.d.ts +15 -0
  72. package/lib/hooks/useCodexSocket.js +84 -0
  73. package/lib/hooks/useCodexSocket.js.map +1 -0
  74. package/lib/index.js +1 -1
  75. package/lib/index.js.map +1 -1
  76. package/lib/panel.d.ts +1 -11
  77. package/lib/panel.js +1 -2815
  78. package/lib/panel.js.map +1 -1
  79. package/lib/protocol.d.ts +235 -0
  80. package/lib/protocol.js +278 -0
  81. package/lib/protocol.js.map +1 -0
  82. package/package.json +13 -3
  83. package/playwright.config.cjs +27 -0
  84. package/playwright.unit.config.cjs +19 -0
  85. package/pyproject.toml +1 -1
  86. package/release.sh +52 -14
  87. package/scripts/run_playwright_e2e.sh +96 -0
  88. package/scripts/run_playwright_freeze_repro.sh +58 -0
  89. package/scripts/run_playwright_queue_repro.sh +60 -0
  90. package/scripts/run_playwright_repro.sh +55 -0
  91. package/src/codexChat.tsx +3914 -0
  92. package/src/codexChatAttachmentDedup.ts +47 -0
  93. package/src/codexChatAttachmentLimit.ts +81 -0
  94. package/src/codexChatAttachmentState.ts +37 -0
  95. package/src/codexChatDocumentUtils.ts +644 -0
  96. package/src/codexChatFormatting.ts +94 -0
  97. package/src/codexChatNotice.ts +95 -0
  98. package/src/codexChatPersistence.ts +191 -0
  99. package/src/codexChatPrimitives.tsx +446 -0
  100. package/src/codexChatRender.tsx +376 -0
  101. package/src/codexChatSessionFactory.ts +79 -0
  102. package/src/codexChatSessionKey.ts +16 -0
  103. package/src/codexChatStorage.ts +36 -0
  104. package/src/codexSessionResolver.ts +56 -0
  105. package/src/handlers/activitySummarizer.ts +369 -0
  106. package/src/handlers/codexMessageTypes.ts +34 -0
  107. package/src/handlers/codexMessageUtils.ts +217 -0
  108. package/src/handlers/handleCodexSocketMessage.ts +204 -0
  109. package/src/handlers/sessionSyncHandler.ts +308 -0
  110. package/src/hooks/useCodexSocket.ts +109 -0
  111. package/src/index.ts +1 -1
  112. package/src/panel.tsx +1 -4184
  113. package/src/protocol.ts +582 -0
  114. package/style/index.css +480 -11
  115. package/test-results/.last-run.json +4 -0
  116. package/test.py +0 -0
  117. package/tests/e2e/cell-output-error-tail.spec.js +156 -0
  118. package/tests/e2e/codex-ui-test-helpers.js +138 -0
  119. package/tests/e2e/fixtures/notebooks/error-output-tail.ipynb +58 -0
  120. package/tests/e2e/fixtures/notebooks/error-output-tail.py +19 -0
  121. package/tests/e2e/fixtures/notebooks/tab1.ipynb +322 -0
  122. package/tests/e2e/fixtures/notebooks/tab1.py +272 -0
  123. package/tests/e2e/fixtures/notebooks/tab2.ipynb +252 -0
  124. package/tests/e2e/fixtures/notebooks/tab2.py +231 -0
  125. package/tests/e2e/fixtures/notebooks/tab3.ipynb +403 -0
  126. package/tests/e2e/fixtures/notebooks/tab3.py +331 -0
  127. package/tests/e2e/fixtures/notebooks/tab4.py +339 -0
  128. package/tests/e2e/freeze-notebook-tabs-repro.spec.js +295 -0
  129. package/tests/e2e/mock-codex-cli-flood.py +127 -0
  130. package/tests/e2e/mock-codex-cli-prompt-echo.py +88 -0
  131. package/tests/e2e/mock-codex-cli.py +95 -0
  132. package/tests/e2e/queue-multitab-repro.spec.js +189 -0
  133. package/tests/test_handlers.py +116 -0
  134. package/tests/test_protocol.py +169 -0
  135. package/tests/test_session_store_limits.py +50 -0
  136. package/tests/unit/codexChatAttachmentDedup.spec.ts +56 -0
  137. package/tests/unit/codexChatAttachmentLimit.spec.ts +57 -0
  138. package/tests/unit/codexChatAttachmentState.spec.ts +71 -0
  139. package/tests/unit/codexChatDocumentUtils.spec.ts +63 -0
  140. package/tests/unit/codexChatLimit.spec.ts +18 -0
  141. package/tests/unit/codexChatNotice.spec.ts +45 -0
  142. package/tests/unit/codexChatPersistence.spec.ts +199 -0
  143. package/tests/unit/codexChatSessionFactory.spec.ts +94 -0
  144. package/tests/unit/codexChatSessionKey.spec.ts +18 -0
  145. package/tests/unit/codexMessageUtils.spec.ts +89 -0
  146. package/tests/unit/codexSessionResolver.spec.ts +92 -0
  147. package/tests/unit/handleCodexSocketMessage.spec.ts +476 -0
  148. package/tsconfig.tsbuildinfo +1 -1
  149. package/webpack.config.js +6 -0
  150. package/jupyterlab_codex/labextension/static/504.335f3447c84ba3d74517.js +0 -2
  151. package/jupyterlab_codex/labextension/static/972.8e856719e40acc1ef4cb.js +0 -1
  152. package/jupyterlab_codex/labextension/static/remoteEntry.a2982f776a1f0f515640.js +0 -1
  153. /package/jupyterlab_codex/labextension/static/{504.335f3447c84ba3d74517.js.LICENSE.txt → 525.224526d045c727069de6.js.LICENSE.txt} +0 -0
@@ -0,0 +1,327 @@
1
+ function truncateMiddle(value, max) {
2
+ if (value.length <= max) {
3
+ return value;
4
+ }
5
+ const ellipsis = '...';
6
+ if (max <= ellipsis.length) {
7
+ return value.slice(0, max);
8
+ }
9
+ const head = Math.max(0, Math.floor((max - ellipsis.length) * 0.6));
10
+ const tail = Math.max(0, max - head - ellipsis.length);
11
+ return `${value.slice(0, head)}${ellipsis}${value.slice(value.length - tail)}`;
12
+ }
13
+ function safePreview(value, max = 220) {
14
+ if (value == null) {
15
+ return '';
16
+ }
17
+ if (typeof value === 'string') {
18
+ return truncateMiddle(value, max);
19
+ }
20
+ if (typeof value === 'number' || typeof value === 'boolean') {
21
+ return String(value);
22
+ }
23
+ try {
24
+ return truncateMiddle(JSON.stringify(value), max);
25
+ }
26
+ catch {
27
+ return '';
28
+ }
29
+ }
30
+ function safeJsonPreview(value, maxChars = 6000) {
31
+ try {
32
+ const text = JSON.stringify(value, null, 2);
33
+ if (text.length <= maxChars) {
34
+ return text;
35
+ }
36
+ return `${text.slice(0, Math.max(0, maxChars - 40))}\n... (truncated)`;
37
+ }
38
+ catch {
39
+ return '';
40
+ }
41
+ }
42
+ function fileNameFromPath(path) {
43
+ const raw = (path || '').trim();
44
+ if (!raw) {
45
+ return '';
46
+ }
47
+ const normalized = raw.replace(/\\/g, '/');
48
+ const parts = normalized.split('/').filter(Boolean);
49
+ return parts[parts.length - 1] || normalized;
50
+ }
51
+ function extractFileChangePaths(item) {
52
+ if (!item || typeof item !== 'object') {
53
+ return [];
54
+ }
55
+ const seen = new Set();
56
+ const paths = [];
57
+ const push = (value) => {
58
+ if (typeof value !== 'string') {
59
+ return;
60
+ }
61
+ const path = value.trim();
62
+ if (!path || seen.has(path)) {
63
+ return;
64
+ }
65
+ seen.add(path);
66
+ paths.push(path);
67
+ };
68
+ const directKeys = [
69
+ 'path',
70
+ 'filename',
71
+ 'filePath',
72
+ 'file_path',
73
+ 'targetPath',
74
+ 'target_path',
75
+ 'newPath',
76
+ 'new_path',
77
+ 'oldPath',
78
+ 'old_path',
79
+ 'sourcePath',
80
+ 'source_path',
81
+ 'destinationPath',
82
+ 'destination_path'
83
+ ];
84
+ for (const key of directKeys) {
85
+ push(item[key]);
86
+ }
87
+ const nestedObjectKeys = ['file', 'target', 'source', 'destination'];
88
+ for (const key of nestedObjectKeys) {
89
+ const nested = item[key];
90
+ if (!nested || typeof nested !== 'object') {
91
+ continue;
92
+ }
93
+ push(nested.path);
94
+ push(nested.filename);
95
+ push(nested.filePath);
96
+ push(nested.file_path);
97
+ }
98
+ const listKeys = ['paths', 'files', 'changes', 'edits'];
99
+ for (const key of listKeys) {
100
+ const list = item[key];
101
+ if (!Array.isArray(list)) {
102
+ continue;
103
+ }
104
+ for (const entry of list) {
105
+ if (typeof entry === 'string') {
106
+ push(entry);
107
+ continue;
108
+ }
109
+ if (!entry || typeof entry !== 'object') {
110
+ continue;
111
+ }
112
+ push(entry.path);
113
+ push(entry.filename);
114
+ push(entry.filePath);
115
+ push(entry.file_path);
116
+ push(entry.targetPath);
117
+ push(entry.target_path);
118
+ push(entry.newPath);
119
+ push(entry.new_path);
120
+ push(entry.oldPath);
121
+ push(entry.old_path);
122
+ }
123
+ }
124
+ // Fallback: recursively scan nested objects for path-like keys.
125
+ if (paths.length === 0) {
126
+ const queue = [item];
127
+ let visited = 0;
128
+ while (queue.length > 0 && visited < 300) {
129
+ const current = queue.shift();
130
+ visited += 1;
131
+ if (!current || typeof current !== 'object') {
132
+ continue;
133
+ }
134
+ if (Array.isArray(current)) {
135
+ for (const value of current) {
136
+ queue.push(value);
137
+ }
138
+ continue;
139
+ }
140
+ for (const [rawKey, value] of Object.entries(current)) {
141
+ const key = rawKey.trim().toLowerCase();
142
+ if (typeof value === 'string' &&
143
+ (key === 'filename' ||
144
+ key.endsWith('path') ||
145
+ key.endsWith('_path') ||
146
+ key.endsWith('filepath') ||
147
+ key.endsWith('file_path'))) {
148
+ push(value);
149
+ }
150
+ if (value && typeof value === 'object') {
151
+ queue.push(value);
152
+ }
153
+ }
154
+ }
155
+ }
156
+ return paths;
157
+ }
158
+ function humanizeToken(value) {
159
+ const input = (value || '').trim();
160
+ if (!input) {
161
+ return '';
162
+ }
163
+ return input
164
+ .split(/[_-]+/)
165
+ .filter(Boolean)
166
+ .map(part => part.charAt(0).toUpperCase() + part.slice(1))
167
+ .join(' ');
168
+ }
169
+ export function summarizeCodexEvent(payload) {
170
+ if (!payload || typeof payload !== 'object') {
171
+ return {
172
+ progress: 'Event',
173
+ progressKind: '',
174
+ activity: { category: 'event', phase: '', title: 'Event', detail: '', raw: safeJsonPreview(payload) }
175
+ };
176
+ }
177
+ const type = (typeof payload.type === 'string' && payload.type) ||
178
+ (typeof payload.event === 'string' && payload.event) ||
179
+ 'event';
180
+ const raw = safeJsonPreview(payload);
181
+ // Common Codex CLI shape: { type: "item.completed|item.started", item: { type: "...", ... } }
182
+ if ((type === 'item.completed' || type === 'item.started') &&
183
+ payload.item &&
184
+ typeof payload.item === 'object') {
185
+ const item = payload.item;
186
+ const itemType = typeof item.type === 'string' ? item.type : '';
187
+ const toolName = (typeof item.tool_name === 'string' && item.tool_name) ||
188
+ (typeof item.tool === 'string' && item.tool) ||
189
+ (typeof item.name === 'string' && item.name) ||
190
+ '';
191
+ const path = (typeof item.path === 'string' && item.path) || (typeof item.filename === 'string' && item.filename) || '';
192
+ const phase = type === 'item.started' ? 'started' : type === 'item.completed' ? 'completed' : '';
193
+ let category = 'event';
194
+ let progressKind = '';
195
+ if (itemType === 'reasoning') {
196
+ category = 'reasoning';
197
+ progressKind = 'reasoning';
198
+ }
199
+ else if (itemType === 'command_execution') {
200
+ category = 'command';
201
+ }
202
+ else if (itemType === 'file_change') {
203
+ category = 'file';
204
+ }
205
+ else if (toolName) {
206
+ category = 'tool';
207
+ }
208
+ let title = '';
209
+ let detail = '';
210
+ if (itemType === 'command_execution') {
211
+ const commandField = item.command ?? item.cmd ?? item.shell_command ?? item.argv ?? item.args ?? item.commandLine ?? item.command_line;
212
+ let commandHint = '';
213
+ if (typeof commandField === 'string') {
214
+ commandHint = commandField;
215
+ }
216
+ else if (Array.isArray(commandField) &&
217
+ commandField.length > 0 &&
218
+ commandField.every((token) => typeof token === 'string')) {
219
+ commandHint = commandField.join(' ');
220
+ }
221
+ else {
222
+ commandHint = safePreview(commandField);
223
+ }
224
+ const exitCode = typeof item.exit_code === 'number' ? item.exit_code : typeof item.exitCode === 'number' ? item.exitCode : null;
225
+ title = phase === 'started' ? 'Running command' : phase === 'completed' ? 'Command finished' : 'Command';
226
+ detail = commandHint || '';
227
+ if (exitCode != null) {
228
+ detail = detail ? `${detail}\n(exit ${exitCode})` : `(exit ${exitCode})`;
229
+ }
230
+ }
231
+ else if (itemType === 'file_change') {
232
+ const filePaths = extractFileChangePaths(item);
233
+ const primaryPath = filePaths[0] || path || '';
234
+ const fileName = fileNameFromPath(primaryPath);
235
+ const baseTitle = phase === 'started' ? 'Update file' : phase === 'completed' ? 'File updated' : 'File change';
236
+ title = fileName ? `${baseTitle}: ${fileName}` : baseTitle;
237
+ detail = filePaths.length > 0 ? filePaths.join('\n') : path || '';
238
+ }
239
+ else if (itemType === 'reasoning') {
240
+ title = phase === 'started' ? 'Reasoning' : phase === 'completed' ? 'Reasoning step' : 'Reasoning';
241
+ detail = toolName ? `(${toolName})` : '';
242
+ }
243
+ else {
244
+ const base = humanizeToken(itemType) || humanizeToken(type) || 'Event';
245
+ title = phase === 'started' ? `${base} started` : phase === 'completed' ? `${base} completed` : base;
246
+ const detailParts = [];
247
+ if (toolName) {
248
+ detailParts.push(`tool: ${toolName}`);
249
+ }
250
+ if (path) {
251
+ detailParts.push(`path: ${path}`);
252
+ }
253
+ detail = detailParts.join('\n');
254
+ }
255
+ if (!title) {
256
+ title = humanizeToken(itemType) || 'Event';
257
+ }
258
+ detail = truncateMiddle(detail, 1400);
259
+ const progressParts = [];
260
+ if (title) {
261
+ progressParts.push(title);
262
+ }
263
+ if (detail) {
264
+ const oneLine = detail.replace(/\s+/g, ' ').trim();
265
+ progressParts.push(truncateMiddle(oneLine, 200));
266
+ }
267
+ const progress = progressParts.join(': ') || humanizeToken(type) || 'Event';
268
+ return {
269
+ progress,
270
+ progressKind,
271
+ activity: {
272
+ category,
273
+ phase,
274
+ title,
275
+ detail,
276
+ raw
277
+ }
278
+ };
279
+ }
280
+ const label = (typeof payload.name === 'string' && payload.name) ||
281
+ (typeof payload.label === 'string' && payload.label) ||
282
+ (typeof payload.tool_name === 'string' && payload.tool_name) ||
283
+ (typeof payload.tool === 'string' && payload.tool) ||
284
+ '';
285
+ if (label && label !== type) {
286
+ const progress = `${humanizeToken(type) || type}: ${truncateMiddle(label, 120)}`;
287
+ return {
288
+ progress,
289
+ progressKind: '',
290
+ activity: { category: 'event', phase: '', title: humanizeToken(type) || type, detail: label, raw }
291
+ };
292
+ }
293
+ const commandHint = safePreview(payload.command);
294
+ if (commandHint) {
295
+ const progress = `${humanizeToken(type) || type}: ${commandHint}`;
296
+ return {
297
+ progress,
298
+ progressKind: '',
299
+ activity: { category: 'event', phase: '', title: humanizeToken(type) || type, detail: commandHint, raw }
300
+ };
301
+ }
302
+ const pathHint = safePreview(payload.path);
303
+ if (pathHint) {
304
+ const progress = `${humanizeToken(type) || type}: ${pathHint}`;
305
+ return {
306
+ progress,
307
+ progressKind: '',
308
+ activity: { category: 'event', phase: '', title: humanizeToken(type) || type, detail: pathHint, raw }
309
+ };
310
+ }
311
+ return {
312
+ progress: humanizeToken(type) || type,
313
+ progressKind: '',
314
+ activity: { category: 'event', phase: '', title: humanizeToken(type) || type, detail: '', raw }
315
+ };
316
+ }
317
+ export function isNoiseCodexEvent(payload) {
318
+ if (!payload || typeof payload !== 'object') {
319
+ return false;
320
+ }
321
+ const type = (typeof payload.type === 'string' && payload.type) ||
322
+ (typeof payload.event === 'string' && payload.event) ||
323
+ '';
324
+ // These are useful for debugging but not meaningful for end users.
325
+ return type === 'thread.started' || type === 'turn.started' || type === 'turn.completed';
326
+ }
327
+ //# sourceMappingURL=activitySummarizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activitySummarizer.js","sourceRoot":"","sources":["../../src/handlers/activitySummarizer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ export type TextRole = 'user' | 'assistant' | 'system';
2
+ export interface HistoryEntry {
3
+ role: TextRole;
4
+ content: string;
5
+ selectionPreview?: {
6
+ locationLabel: string;
7
+ previewText: string;
8
+ };
9
+ cellOutputPreview?: {
10
+ locationLabel: string;
11
+ previewText: string;
12
+ };
13
+ }
14
+ export interface RateLimitWindowSnapshot {
15
+ usedPercent: number | null;
16
+ windowMinutes: number | null;
17
+ resetsAt: number | null;
18
+ }
19
+ export interface ContextWindowSnapshot {
20
+ windowTokens: number | null;
21
+ usedTokens: number | null;
22
+ leftTokens: number | null;
23
+ usedPercent: number | null;
24
+ }
25
+ export interface CodexRateLimitsSnapshot {
26
+ updatedAt: string | null;
27
+ primary: RateLimitWindowSnapshot | null;
28
+ secondary: RateLimitWindowSnapshot | null;
29
+ contextWindow: ContextWindowSnapshot | null;
30
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=codexMessageTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codexMessageTypes.js","sourceRoot":"","sources":["../../src/handlers/codexMessageTypes.ts"],"names":[],"mappings":""}
@@ -0,0 +1,46 @@
1
+ import type { CodexRateLimitsSnapshot, ContextWindowSnapshot, HistoryEntry, RateLimitWindowSnapshot, TextRole } from './codexMessageTypes';
2
+ export type { HistoryEntry, TextRole };
3
+ export type ProgressKind = '' | 'reasoning';
4
+ export type ActivityPhase = 'started' | 'completed' | '';
5
+ export type ActivityCategory = 'reasoning' | 'command' | 'file' | 'tool' | 'event';
6
+ export interface SelectionPreview {
7
+ locationLabel: string;
8
+ previewText: string;
9
+ }
10
+ export interface MessageContextPreview {
11
+ selectionPreview?: SelectionPreview;
12
+ cellOutputPreview?: SelectionPreview;
13
+ }
14
+ export interface ActivityItem {
15
+ category: ActivityCategory;
16
+ phase: ActivityPhase;
17
+ title: string;
18
+ detail: string;
19
+ raw: string;
20
+ }
21
+ export interface ActivitySummary {
22
+ activity: Omit<ActivityItem, 'id' | 'ts'>;
23
+ progress: string;
24
+ progressKind: ProgressKind;
25
+ }
26
+ export interface SessionPreviewSplit {
27
+ selectionPreview?: unknown;
28
+ cellOutputPreview?: unknown;
29
+ }
30
+ export declare function truncateEnd(text: string, max: number): string;
31
+ export declare function coerceSelectionPreview(value: unknown, options?: {
32
+ maxChars?: number;
33
+ normalize?: (value: string) => string;
34
+ }): SelectionPreview | undefined;
35
+ export declare function coerceMessageContextPreview(value: unknown, options?: {
36
+ maxChars?: number;
37
+ normalize?: (value: string) => string;
38
+ }): MessageContextPreview | undefined;
39
+ export declare function coerceSessionHistory(raw: unknown, options?: {
40
+ maxChars?: number;
41
+ normalize?: (value: string) => string;
42
+ }): HistoryEntry[];
43
+ export declare function coerceRateLimitWindow(raw: unknown): RateLimitWindowSnapshot | null;
44
+ export declare function coerceContextWindowSnapshot(raw: unknown): ContextWindowSnapshot | null;
45
+ export declare function coerceRateLimitsSnapshot(raw: unknown): CodexRateLimitsSnapshot | null;
46
+ export declare function splitStoredMessagePreview(value: unknown): SessionPreviewSplit;
@@ -0,0 +1,144 @@
1
+ export function truncateEnd(text, max) {
2
+ if (text.length <= max) {
3
+ return text;
4
+ }
5
+ if (max <= 3) {
6
+ return text.slice(0, max);
7
+ }
8
+ return `${text.slice(0, max - 3)}...`;
9
+ }
10
+ export function coerceSelectionPreview(value, options = {}) {
11
+ if (!value || typeof value !== 'object') {
12
+ return undefined;
13
+ }
14
+ const raw = value;
15
+ const locationLabel = typeof raw.locationLabel === 'string' ? raw.locationLabel.trim() : '';
16
+ const normalizer = options.normalize ?? ((text) => text.trim());
17
+ const maxChars = options.maxChars ?? 500;
18
+ const previewText = typeof raw.previewText === 'string' ? truncateEnd(normalizer(raw.previewText), maxChars) : '';
19
+ if (!locationLabel || !previewText) {
20
+ return undefined;
21
+ }
22
+ return { locationLabel, previewText };
23
+ }
24
+ export function coerceMessageContextPreview(value, options = {}) {
25
+ if (!value || typeof value !== 'object') {
26
+ return undefined;
27
+ }
28
+ const raw = value;
29
+ const selectionPreview = coerceSelectionPreview(raw.selectionPreview, options);
30
+ const cellOutputPreview = coerceSelectionPreview(raw.cellOutputPreview, options);
31
+ if (selectionPreview || cellOutputPreview) {
32
+ return {
33
+ ...(selectionPreview ? { selectionPreview } : {}),
34
+ ...(cellOutputPreview ? { cellOutputPreview } : {})
35
+ };
36
+ }
37
+ // Legacy format: a single preview object was stored directly as selection preview.
38
+ const legacySelectionPreview = coerceSelectionPreview(raw, options);
39
+ if (legacySelectionPreview) {
40
+ return { selectionPreview: legacySelectionPreview };
41
+ }
42
+ return undefined;
43
+ }
44
+ export function coerceSessionHistory(raw, options = {}) {
45
+ if (!Array.isArray(raw)) {
46
+ return [];
47
+ }
48
+ const result = [];
49
+ for (const item of raw) {
50
+ if (!item || typeof item !== 'object') {
51
+ continue;
52
+ }
53
+ const role = item.role;
54
+ const content = item.content;
55
+ if ((role !== 'user' && role !== 'assistant' && role !== 'system') || typeof content !== 'string') {
56
+ continue;
57
+ }
58
+ const selectionPreview = coerceSelectionPreview(item.selectionPreview, options);
59
+ const cellOutputPreview = coerceSelectionPreview(item.cellOutputPreview, options);
60
+ result.push({
61
+ role,
62
+ content,
63
+ selectionPreview,
64
+ cellOutputPreview
65
+ });
66
+ }
67
+ return result;
68
+ }
69
+ function coerceFiniteNumber(value) {
70
+ if (typeof value === 'number' && Number.isFinite(value)) {
71
+ return value;
72
+ }
73
+ if (typeof value === 'string') {
74
+ const trimmed = value.trim();
75
+ if (!trimmed) {
76
+ return null;
77
+ }
78
+ const parsed = Number(trimmed);
79
+ return Number.isFinite(parsed) ? parsed : null;
80
+ }
81
+ return null;
82
+ }
83
+ export function coerceRateLimitWindow(raw) {
84
+ if (!raw || typeof raw !== 'object') {
85
+ return null;
86
+ }
87
+ const record = raw;
88
+ const usedPercent = coerceFiniteNumber(record.usedPercent);
89
+ const windowMinutesValue = coerceFiniteNumber(record.windowMinutes);
90
+ const resetsAtValue = coerceFiniteNumber(record.resetsAt);
91
+ const windowMinutes = windowMinutesValue === null ? null : Math.round(windowMinutesValue);
92
+ const resetsAt = resetsAtValue === null ? null : Math.round(resetsAtValue);
93
+ return { usedPercent, windowMinutes, resetsAt };
94
+ }
95
+ export function coerceContextWindowSnapshot(raw) {
96
+ if (!raw || typeof raw !== 'object') {
97
+ return null;
98
+ }
99
+ const record = raw;
100
+ const windowTokensValue = coerceFiniteNumber(record.windowTokens);
101
+ const usedTokensValue = coerceFiniteNumber(record.usedTokens);
102
+ const leftTokensValue = coerceFiniteNumber(record.leftTokens);
103
+ const usedPercent = coerceFiniteNumber(record.usedPercent);
104
+ const windowTokens = windowTokensValue === null ? null : Math.round(windowTokensValue);
105
+ const usedTokens = usedTokensValue === null ? null : Math.round(usedTokensValue);
106
+ const leftTokens = leftTokensValue === null ? null : Math.round(leftTokensValue);
107
+ if (windowTokens == null && usedTokens == null && leftTokens == null && usedPercent == null) {
108
+ return null;
109
+ }
110
+ return { windowTokens, usedTokens, leftTokens, usedPercent };
111
+ }
112
+ export function coerceRateLimitsSnapshot(raw) {
113
+ if (!raw || typeof raw !== 'object') {
114
+ return null;
115
+ }
116
+ const rawRecord = raw;
117
+ const updatedAt = typeof rawRecord.updatedAt === 'string' && rawRecord.updatedAt.trim() ? rawRecord.updatedAt : null;
118
+ return {
119
+ updatedAt,
120
+ primary: coerceRateLimitWindow(rawRecord.primary),
121
+ secondary: coerceRateLimitWindow(rawRecord.secondary),
122
+ contextWindow: coerceContextWindowSnapshot(rawRecord.contextWindow)
123
+ };
124
+ }
125
+ export function splitStoredMessagePreview(value) {
126
+ if (!value || typeof value !== 'object') {
127
+ return {};
128
+ }
129
+ const raw = value;
130
+ const hasNestedPreview = Object.prototype.hasOwnProperty.call(raw, 'selectionPreview') ||
131
+ Object.prototype.hasOwnProperty.call(raw, 'cellOutputPreview');
132
+ if (hasNestedPreview) {
133
+ return {
134
+ selectionPreview: raw.selectionPreview,
135
+ cellOutputPreview: raw.cellOutputPreview
136
+ };
137
+ }
138
+ // Legacy format: a single preview object was stored directly as selectionPreview.
139
+ if (Object.prototype.hasOwnProperty.call(raw, 'locationLabel') && Object.prototype.hasOwnProperty.call(raw, 'previewText')) {
140
+ return { selectionPreview: raw };
141
+ }
142
+ return {};
143
+ }
144
+ //# sourceMappingURL=codexMessageUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codexMessageUtils.js","sourceRoot":"","sources":["../../src/handlers/codexMessageUtils.ts"],"names":[],"mappings":"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"}