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,47 @@
1
+ import { normalizeSelectionPreviewText, type NotebookMode } from './codexChatDocumentUtils';
2
+
3
+ const ACTIVE_CELL_ATTACHMENT_SIGNATURE_SEPARATOR = '\u241f';
4
+ const ACTIVE_CELL_ATTACHMENT_KIND_SELECTION = 'selection';
5
+ const ACTIVE_CELL_ATTACHMENT_KIND_OUTPUT = 'output';
6
+
7
+ export type ActiveCellAttachmentSignatureInput = {
8
+ notebookMode: NotebookMode;
9
+ text: string;
10
+ locationLabel?: string;
11
+ };
12
+
13
+ export function makeActiveCellAttachmentDedupKey(sessionKey: string, threadId: string): string {
14
+ const normalizedThreadId = (threadId || '').trim();
15
+ if (normalizedThreadId) {
16
+ return `thread:${normalizedThreadId}`;
17
+ }
18
+ return `session:${(sessionKey || '').trim()}`;
19
+ }
20
+
21
+ function buildActiveCellAttachmentSignature(kind: string, input: ActiveCellAttachmentSignatureInput): string {
22
+ const notebookMode = input.notebookMode;
23
+ const text = normalizeSelectionPreviewText(input.text || '');
24
+ const locationLabel = (input.locationLabel || '').trim();
25
+
26
+ return [
27
+ kind,
28
+ notebookMode,
29
+ locationLabel,
30
+ text
31
+ ].join(ACTIVE_CELL_ATTACHMENT_SIGNATURE_SEPARATOR);
32
+ }
33
+
34
+ export function buildActiveCellSelectionSignature(input: ActiveCellAttachmentSignatureInput): string {
35
+ return buildActiveCellAttachmentSignature(ACTIVE_CELL_ATTACHMENT_KIND_SELECTION, input);
36
+ }
37
+
38
+ export function buildActiveCellOutputSignature(input: ActiveCellAttachmentSignatureInput): string {
39
+ return buildActiveCellAttachmentSignature(ACTIVE_CELL_ATTACHMENT_KIND_OUTPUT, input);
40
+ }
41
+
42
+ export function isDuplicateActiveCellAttachmentSignature(previous: string | undefined, next: string): boolean {
43
+ if (!previous || !next) {
44
+ return false;
45
+ }
46
+ return previous === next;
47
+ }
@@ -0,0 +1,81 @@
1
+ export type ActiveCellAttachmentLimitResult = {
2
+ selection: string;
3
+ cellOutput: string;
4
+ selectionTruncated: boolean;
5
+ cellOutputTruncated: boolean;
6
+ };
7
+
8
+ export type SentAttachmentTruncationResult = {
9
+ selectionTruncated: boolean;
10
+ cellOutputTruncated: boolean;
11
+ };
12
+
13
+ function clampNonNegativeInteger(value: number): number {
14
+ if (!Number.isFinite(value)) {
15
+ return 0;
16
+ }
17
+ return Math.max(0, Math.floor(value));
18
+ }
19
+
20
+ function sliceByCharLimit(value: string, limit: number): string {
21
+ if (limit <= 0) {
22
+ return '';
23
+ }
24
+ if (value.length <= limit) {
25
+ return value;
26
+ }
27
+ return value.slice(0, limit);
28
+ }
29
+
30
+ export function limitActiveCellAttachmentPayload(
31
+ selection: string,
32
+ cellOutput: string,
33
+ maxSelectionChars: number,
34
+ maxCellOutputChars: number
35
+ ): ActiveCellAttachmentLimitResult {
36
+ const sourceSelection = typeof selection === 'string' ? selection : '';
37
+ const sourceCellOutput = typeof cellOutput === 'string' ? cellOutput : '';
38
+ const selectionLimit = clampNonNegativeInteger(maxSelectionChars);
39
+ const cellOutputLimit = clampNonNegativeInteger(maxCellOutputChars);
40
+ const nextSelection = sliceByCharLimit(sourceSelection, selectionLimit);
41
+ const nextCellOutput = sliceByCharLimit(sourceCellOutput, cellOutputLimit);
42
+ return {
43
+ selection: nextSelection,
44
+ cellOutput: nextCellOutput,
45
+ selectionTruncated: nextSelection.length < sourceSelection.length,
46
+ cellOutputTruncated: nextCellOutput.length < sourceCellOutput.length
47
+ };
48
+ }
49
+
50
+ export function buildAttachmentTruncationNotice(
51
+ selectionTruncated: boolean,
52
+ cellOutputTruncated: boolean,
53
+ maxSelectionChars: number,
54
+ maxCellOutputChars: number
55
+ ): string | null {
56
+ if (!selectionTruncated && !cellOutputTruncated) {
57
+ return null;
58
+ }
59
+
60
+ const selectionLimit = String(clampNonNegativeInteger(maxSelectionChars));
61
+ const cellOutputLimit = String(clampNonNegativeInteger(maxCellOutputChars));
62
+ if (selectionTruncated && cellOutputTruncated) {
63
+ return `Attached input and output were truncated before sending (input: ${selectionLimit} chars, output: ${cellOutputLimit} chars). The full input can be checked directly from the source file/cell.`;
64
+ }
65
+ if (selectionTruncated) {
66
+ return `Attached input was truncated before sending to stay within ${selectionLimit} characters. The full input can be checked directly from the source file/cell.`;
67
+ }
68
+ return `Attached output was truncated before sending to stay within ${cellOutputLimit} characters.`;
69
+ }
70
+
71
+ export function resolveSentAttachmentTruncation(input: {
72
+ includeSelection: boolean;
73
+ includeCellOutput: boolean;
74
+ selectionTruncated: boolean;
75
+ cellOutputTruncated: boolean;
76
+ }): SentAttachmentTruncationResult {
77
+ return {
78
+ selectionTruncated: input.includeSelection && input.selectionTruncated,
79
+ cellOutputTruncated: input.includeCellOutput && input.cellOutputTruncated
80
+ };
81
+ }
@@ -0,0 +1,37 @@
1
+ import type { NotebookMode } from './codexChatDocumentUtils';
2
+
3
+ export type CellAttachmentStateInput = {
4
+ includeActiveCell: boolean;
5
+ includeActiveCellOutput: boolean;
6
+ notebookMode: NotebookMode;
7
+ isNotebookEditor: boolean;
8
+ currentNotebookPath: string;
9
+ pairedOk: boolean | null | undefined;
10
+ };
11
+
12
+ export type CellAttachmentState = {
13
+ showBadge: boolean;
14
+ contentEnabled: boolean;
15
+ outputEnabled: boolean;
16
+ };
17
+
18
+ export function resolveCellAttachmentState(input: CellAttachmentStateInput): CellAttachmentState {
19
+ const canShowCellAttachmentControl =
20
+ input.isNotebookEditor &&
21
+ (input.notebookMode === 'ipynb' || input.notebookMode === 'jupytext_py');
22
+ const canAttachCurrentCellContent =
23
+ input.includeActiveCell &&
24
+ canShowCellAttachmentControl;
25
+ const canAttachCurrentCellOutput =
26
+ canAttachCurrentCellContent && input.includeActiveCellOutput;
27
+ const showBadge =
28
+ canShowCellAttachmentControl &&
29
+ input.currentNotebookPath.length > 0 &&
30
+ input.pairedOk !== false;
31
+
32
+ return {
33
+ showBadge,
34
+ contentEnabled: canAttachCurrentCellContent,
35
+ outputEnabled: canAttachCurrentCellOutput
36
+ };
37
+ }