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.
- package/.claude/settings.local.json +9 -0
- package/.github/workflows/unit-tests.yml +27 -0
- package/.jupyterlab-playwright.log +0 -0
- package/README.md +83 -9
- package/docs/images/codex-sidebar-screenshot.png +0 -0
- package/jupyterlab_codex/handlers.py +938 -297
- package/jupyterlab_codex/labextension/package.json +13 -3
- package/jupyterlab_codex/labextension/static/525.224526d045c727069de6.js +2 -0
- package/jupyterlab_codex/labextension/static/737.e7de3ad9dd6ded798340.js +1 -0
- package/jupyterlab_codex/labextension/static/remoteEntry.6ef5e7167763a316c000.js +1 -0
- package/jupyterlab_codex/protocol.py +297 -0
- package/jupyterlab_codex/runner.py +58 -15
- package/jupyterlab_codex/sessions.py +582 -97
- package/lib/codexChat.d.ts +13 -0
- package/lib/codexChat.js +2506 -0
- package/lib/codexChat.js.map +1 -0
- package/lib/codexChatAttachmentDedup.d.ts +10 -0
- package/lib/codexChatAttachmentDedup.js +35 -0
- package/lib/codexChatAttachmentDedup.js.map +1 -0
- package/lib/codexChatAttachmentLimit.d.ts +18 -0
- package/lib/codexChatAttachmentLimit.js +50 -0
- package/lib/codexChatAttachmentLimit.js.map +1 -0
- package/lib/codexChatAttachmentState.d.ts +15 -0
- package/lib/codexChatAttachmentState.js +16 -0
- package/lib/codexChatAttachmentState.js.map +1 -0
- package/lib/codexChatDocumentUtils.d.ts +70 -0
- package/lib/codexChatDocumentUtils.js +506 -0
- package/lib/codexChatDocumentUtils.js.map +1 -0
- package/lib/codexChatFormatting.d.ts +11 -0
- package/lib/codexChatFormatting.js +83 -0
- package/lib/codexChatFormatting.js.map +1 -0
- package/lib/codexChatNotice.d.ts +3 -0
- package/lib/codexChatNotice.js +74 -0
- package/lib/codexChatNotice.js.map +1 -0
- package/lib/codexChatPersistence.d.ts +35 -0
- package/lib/codexChatPersistence.js +158 -0
- package/lib/codexChatPersistence.js.map +1 -0
- package/lib/codexChatPrimitives.d.ts +44 -0
- package/lib/codexChatPrimitives.js +156 -0
- package/lib/codexChatPrimitives.js.map +1 -0
- package/lib/codexChatRender.d.ts +24 -0
- package/lib/codexChatRender.js +293 -0
- package/lib/codexChatRender.js.map +1 -0
- package/lib/codexChatSessionFactory.d.ts +15 -0
- package/lib/codexChatSessionFactory.js +45 -0
- package/lib/codexChatSessionFactory.js.map +1 -0
- package/lib/codexChatSessionKey.d.ts +3 -0
- package/lib/codexChatSessionKey.js +14 -0
- package/lib/codexChatSessionKey.js.map +1 -0
- package/lib/codexChatStorage.d.ts +4 -0
- package/lib/codexChatStorage.js +37 -0
- package/lib/codexChatStorage.js.map +1 -0
- package/lib/codexSessionResolver.d.ts +12 -0
- package/lib/codexSessionResolver.js +38 -0
- package/lib/codexSessionResolver.js.map +1 -0
- package/lib/handlers/activitySummarizer.d.ts +15 -0
- package/lib/handlers/activitySummarizer.js +327 -0
- package/lib/handlers/activitySummarizer.js.map +1 -0
- package/lib/handlers/codexMessageTypes.d.ts +30 -0
- package/lib/handlers/codexMessageTypes.js +2 -0
- package/lib/handlers/codexMessageTypes.js.map +1 -0
- package/lib/handlers/codexMessageUtils.d.ts +46 -0
- package/lib/handlers/codexMessageUtils.js +144 -0
- package/lib/handlers/codexMessageUtils.js.map +1 -0
- package/lib/handlers/handleCodexSocketMessage.d.ts +107 -0
- package/lib/handlers/handleCodexSocketMessage.js +78 -0
- package/lib/handlers/handleCodexSocketMessage.js.map +1 -0
- package/lib/handlers/sessionSyncHandler.d.ts +34 -0
- package/lib/handlers/sessionSyncHandler.js +181 -0
- package/lib/handlers/sessionSyncHandler.js.map +1 -0
- package/lib/hooks/useCodexSocket.d.ts +15 -0
- package/lib/hooks/useCodexSocket.js +84 -0
- package/lib/hooks/useCodexSocket.js.map +1 -0
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/panel.d.ts +1 -11
- package/lib/panel.js +1 -2815
- package/lib/panel.js.map +1 -1
- package/lib/protocol.d.ts +235 -0
- package/lib/protocol.js +278 -0
- package/lib/protocol.js.map +1 -0
- package/package.json +13 -3
- package/playwright.config.cjs +27 -0
- package/playwright.unit.config.cjs +19 -0
- package/pyproject.toml +1 -1
- package/release.sh +52 -14
- package/scripts/run_playwright_e2e.sh +96 -0
- package/scripts/run_playwright_freeze_repro.sh +58 -0
- package/scripts/run_playwright_queue_repro.sh +60 -0
- package/scripts/run_playwright_repro.sh +55 -0
- package/src/codexChat.tsx +3914 -0
- package/src/codexChatAttachmentDedup.ts +47 -0
- package/src/codexChatAttachmentLimit.ts +81 -0
- package/src/codexChatAttachmentState.ts +37 -0
- package/src/codexChatDocumentUtils.ts +644 -0
- package/src/codexChatFormatting.ts +94 -0
- package/src/codexChatNotice.ts +95 -0
- package/src/codexChatPersistence.ts +191 -0
- package/src/codexChatPrimitives.tsx +446 -0
- package/src/codexChatRender.tsx +376 -0
- package/src/codexChatSessionFactory.ts +79 -0
- package/src/codexChatSessionKey.ts +16 -0
- package/src/codexChatStorage.ts +36 -0
- package/src/codexSessionResolver.ts +56 -0
- package/src/handlers/activitySummarizer.ts +369 -0
- package/src/handlers/codexMessageTypes.ts +34 -0
- package/src/handlers/codexMessageUtils.ts +217 -0
- package/src/handlers/handleCodexSocketMessage.ts +204 -0
- package/src/handlers/sessionSyncHandler.ts +308 -0
- package/src/hooks/useCodexSocket.ts +109 -0
- package/src/index.ts +1 -1
- package/src/panel.tsx +1 -4184
- package/src/protocol.ts +582 -0
- package/style/index.css +480 -11
- package/test-results/.last-run.json +4 -0
- package/test.py +0 -0
- package/tests/e2e/cell-output-error-tail.spec.js +156 -0
- package/tests/e2e/codex-ui-test-helpers.js +138 -0
- package/tests/e2e/fixtures/notebooks/error-output-tail.ipynb +58 -0
- package/tests/e2e/fixtures/notebooks/error-output-tail.py +19 -0
- package/tests/e2e/fixtures/notebooks/tab1.ipynb +322 -0
- package/tests/e2e/fixtures/notebooks/tab1.py +272 -0
- package/tests/e2e/fixtures/notebooks/tab2.ipynb +252 -0
- package/tests/e2e/fixtures/notebooks/tab2.py +231 -0
- package/tests/e2e/fixtures/notebooks/tab3.ipynb +403 -0
- package/tests/e2e/fixtures/notebooks/tab3.py +331 -0
- package/tests/e2e/fixtures/notebooks/tab4.py +339 -0
- package/tests/e2e/freeze-notebook-tabs-repro.spec.js +295 -0
- package/tests/e2e/mock-codex-cli-flood.py +127 -0
- package/tests/e2e/mock-codex-cli-prompt-echo.py +88 -0
- package/tests/e2e/mock-codex-cli.py +95 -0
- package/tests/e2e/queue-multitab-repro.spec.js +189 -0
- package/tests/test_handlers.py +116 -0
- package/tests/test_protocol.py +169 -0
- package/tests/test_session_store_limits.py +50 -0
- package/tests/unit/codexChatAttachmentDedup.spec.ts +56 -0
- package/tests/unit/codexChatAttachmentLimit.spec.ts +57 -0
- package/tests/unit/codexChatAttachmentState.spec.ts +71 -0
- package/tests/unit/codexChatDocumentUtils.spec.ts +63 -0
- package/tests/unit/codexChatLimit.spec.ts +18 -0
- package/tests/unit/codexChatNotice.spec.ts +45 -0
- package/tests/unit/codexChatPersistence.spec.ts +199 -0
- package/tests/unit/codexChatSessionFactory.spec.ts +94 -0
- package/tests/unit/codexChatSessionKey.spec.ts +18 -0
- package/tests/unit/codexMessageUtils.spec.ts +89 -0
- package/tests/unit/codexSessionResolver.spec.ts +92 -0
- package/tests/unit/handleCodexSocketMessage.spec.ts +476 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/webpack.config.js +6 -0
- package/jupyterlab_codex/labextension/static/504.335f3447c84ba3d74517.js +0 -2
- package/jupyterlab_codex/labextension/static/972.8e856719e40acc1ef4cb.js +0 -1
- package/jupyterlab_codex/labextension/static/remoteEntry.a2982f776a1f0f515640.js +0 -1
- /package/jupyterlab_codex/labextension/static/{504.335f3447c84ba3d74517.js.LICENSE.txt → 525.224526d045c727069de6.js.LICENSE.txt} +0 -0
package/src/protocol.ts
ADDED
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
export const PROTOCOL_VERSION = '1.0.0' as const;
|
|
2
|
+
|
|
3
|
+
export type ServerProtocolVersion = typeof PROTOCOL_VERSION;
|
|
4
|
+
export type ProtocolVersion = string;
|
|
5
|
+
|
|
6
|
+
export type RunMode = 'resume' | 'fallback';
|
|
7
|
+
export type StatusState = 'ready' | 'running';
|
|
8
|
+
|
|
9
|
+
export interface SelectionPreview {
|
|
10
|
+
locationLabel: string;
|
|
11
|
+
previewText: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface ModelCatalogEntry {
|
|
15
|
+
model: string;
|
|
16
|
+
displayName: string;
|
|
17
|
+
reasoningEfforts?: string[];
|
|
18
|
+
defaultReasoningEffort?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ServerMessageBase {
|
|
22
|
+
protocolVersion?: ProtocolVersion;
|
|
23
|
+
type: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ServerCliDefaultsMessage extends ServerMessageBase {
|
|
27
|
+
type: 'cli_defaults';
|
|
28
|
+
model?: string | null;
|
|
29
|
+
reasoningEffort?: string | null;
|
|
30
|
+
availableModels?: ModelCatalogEntry[];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface ServerRateLimitsMessage extends ServerMessageBase {
|
|
34
|
+
type: 'rate_limits';
|
|
35
|
+
snapshot: unknown;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type ServerSessionResolution =
|
|
39
|
+
| 'client'
|
|
40
|
+
| 'client-new'
|
|
41
|
+
| 'force-new'
|
|
42
|
+
| 'mapping'
|
|
43
|
+
| 'mapping-on-missing'
|
|
44
|
+
| 'mapping-on-mismatch'
|
|
45
|
+
| 'new'
|
|
46
|
+
| 'new-on-mismatch';
|
|
47
|
+
|
|
48
|
+
export interface ServerDeleteAllSessionsMessage extends ServerMessageBase {
|
|
49
|
+
type: 'delete_all_sessions';
|
|
50
|
+
ok: boolean;
|
|
51
|
+
deletedCount: number;
|
|
52
|
+
failedCount: number;
|
|
53
|
+
message: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface ServerStatusMessage extends ServerMessageBase {
|
|
57
|
+
type: 'status';
|
|
58
|
+
state: StatusState;
|
|
59
|
+
runId?: string;
|
|
60
|
+
sessionId?: string;
|
|
61
|
+
sessionContextKey?: string;
|
|
62
|
+
notebookPath?: string;
|
|
63
|
+
runMode?: RunMode;
|
|
64
|
+
pairedOk?: boolean;
|
|
65
|
+
pairedPath?: string;
|
|
66
|
+
pairedOsPath?: string;
|
|
67
|
+
pairedMessage?: string;
|
|
68
|
+
notebookMode?: string;
|
|
69
|
+
sessionResolution?: ServerSessionResolution | string;
|
|
70
|
+
sessionResolutionNotice?: string;
|
|
71
|
+
history?: Array<{
|
|
72
|
+
role: 'user' | 'assistant' | 'system';
|
|
73
|
+
content: string;
|
|
74
|
+
selectionPreview?: SelectionPreview;
|
|
75
|
+
cellOutputPreview?: SelectionPreview;
|
|
76
|
+
}>;
|
|
77
|
+
effectiveSandbox?: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface ServerOutputMessage extends ServerMessageBase {
|
|
81
|
+
type: 'output';
|
|
82
|
+
runId: string;
|
|
83
|
+
sessionId: string;
|
|
84
|
+
sessionContextKey?: string;
|
|
85
|
+
notebookPath: string;
|
|
86
|
+
role: 'user' | 'assistant' | 'system';
|
|
87
|
+
text: string;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface ServerEventMessage extends ServerMessageBase {
|
|
91
|
+
type: 'event';
|
|
92
|
+
runId: string;
|
|
93
|
+
sessionId: string;
|
|
94
|
+
sessionContextKey?: string;
|
|
95
|
+
notebookPath: string;
|
|
96
|
+
payload: unknown;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface ServerDoneMessage extends ServerMessageBase {
|
|
100
|
+
type: 'done';
|
|
101
|
+
runId: string;
|
|
102
|
+
sessionId: string;
|
|
103
|
+
sessionContextKey?: string;
|
|
104
|
+
notebookPath: string;
|
|
105
|
+
exitCode: number | null;
|
|
106
|
+
cancelled?: boolean;
|
|
107
|
+
fileChanged?: boolean;
|
|
108
|
+
runMode?: RunMode;
|
|
109
|
+
pairedOk?: boolean;
|
|
110
|
+
pairedPath?: string;
|
|
111
|
+
pairedOsPath?: string;
|
|
112
|
+
pairedMessage?: string;
|
|
113
|
+
notebookMode?: string;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export interface ServerErrorMessage extends ServerMessageBase {
|
|
117
|
+
type: 'error';
|
|
118
|
+
runId?: string;
|
|
119
|
+
sessionId?: string;
|
|
120
|
+
sessionContextKey?: string;
|
|
121
|
+
notebookPath?: string;
|
|
122
|
+
message: string;
|
|
123
|
+
runMode?: RunMode;
|
|
124
|
+
suggestedCommandPath?: string;
|
|
125
|
+
pairedOk?: boolean;
|
|
126
|
+
pairedPath?: string;
|
|
127
|
+
pairedOsPath?: string;
|
|
128
|
+
pairedMessage?: string;
|
|
129
|
+
notebookMode?: string;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export type ServerMessage =
|
|
133
|
+
| ServerCliDefaultsMessage
|
|
134
|
+
| ServerRateLimitsMessage
|
|
135
|
+
| ServerDeleteAllSessionsMessage
|
|
136
|
+
| ServerStatusMessage
|
|
137
|
+
| ServerOutputMessage
|
|
138
|
+
| ServerEventMessage
|
|
139
|
+
| ServerDoneMessage
|
|
140
|
+
| ServerErrorMessage;
|
|
141
|
+
|
|
142
|
+
export interface ParsedServerStartSessionMessage {
|
|
143
|
+
type: 'start_session';
|
|
144
|
+
sessionId: string;
|
|
145
|
+
sessionContextKey: string;
|
|
146
|
+
notebookPath: string;
|
|
147
|
+
forceNewThread: boolean;
|
|
148
|
+
commandPath: string;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export interface ParsedClientSendMessage {
|
|
152
|
+
type: 'send';
|
|
153
|
+
sessionId: string;
|
|
154
|
+
sessionContextKey: string;
|
|
155
|
+
content: string;
|
|
156
|
+
notebookPath: string;
|
|
157
|
+
commandPath: string;
|
|
158
|
+
model: string;
|
|
159
|
+
reasoningEffort: string;
|
|
160
|
+
sandbox: string;
|
|
161
|
+
selection: string;
|
|
162
|
+
cellOutput: string;
|
|
163
|
+
images: unknown[];
|
|
164
|
+
uiSelectionPreview?: unknown;
|
|
165
|
+
uiCellOutputPreview?: unknown;
|
|
166
|
+
selectionTruncated: boolean;
|
|
167
|
+
cellOutputTruncated: boolean;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export interface ParsedClientDeleteSessionMessage {
|
|
171
|
+
type: 'delete_session';
|
|
172
|
+
sessionId: string;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export interface ParsedClientCancelMessage {
|
|
176
|
+
type: 'cancel';
|
|
177
|
+
runId: string;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export interface ParsedClientEndSessionMessage {
|
|
181
|
+
type: 'end_session';
|
|
182
|
+
sessionId: string;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export interface ParsedClientRefreshRateLimitsMessage {
|
|
186
|
+
type: 'refresh_rate_limits';
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export interface ParsedClientDeleteAllSessionsMessage {
|
|
190
|
+
type: 'delete_all_sessions';
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export interface ParsedClientStartSessionMessage {
|
|
194
|
+
type: 'start_session';
|
|
195
|
+
sessionId: string;
|
|
196
|
+
notebookPath: string;
|
|
197
|
+
sessionContextKey: string;
|
|
198
|
+
forceNewThread: boolean;
|
|
199
|
+
commandPath: string;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export type ParsedClientMessage =
|
|
203
|
+
| ParsedClientSendMessage
|
|
204
|
+
| ParsedClientDeleteSessionMessage
|
|
205
|
+
| ParsedClientDeleteAllSessionsMessage
|
|
206
|
+
| ParsedClientCancelMessage
|
|
207
|
+
| ParsedClientEndSessionMessage
|
|
208
|
+
| ParsedClientRefreshRateLimitsMessage
|
|
209
|
+
| ParsedClientStartSessionMessage;
|
|
210
|
+
|
|
211
|
+
export interface ClientStartSessionMessage {
|
|
212
|
+
type: 'start_session';
|
|
213
|
+
sessionId: string;
|
|
214
|
+
notebookPath: string;
|
|
215
|
+
sessionContextKey: string;
|
|
216
|
+
forceNewThread: boolean;
|
|
217
|
+
commandPath?: string;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export interface ClientSendMessage {
|
|
221
|
+
type: 'send';
|
|
222
|
+
sessionId: string;
|
|
223
|
+
sessionContextKey: string;
|
|
224
|
+
content: string;
|
|
225
|
+
notebookPath: string;
|
|
226
|
+
commandPath?: string;
|
|
227
|
+
model: string;
|
|
228
|
+
reasoningEffort: string;
|
|
229
|
+
sandbox: string;
|
|
230
|
+
selection?: string;
|
|
231
|
+
cellOutput?: string;
|
|
232
|
+
images?: { name: string; dataUrl: string }[];
|
|
233
|
+
uiSelectionPreview?: unknown;
|
|
234
|
+
uiCellOutputPreview?: unknown;
|
|
235
|
+
selectionTruncated?: boolean;
|
|
236
|
+
cellOutputTruncated?: boolean;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export interface ClientCancelMessage {
|
|
240
|
+
type: 'cancel';
|
|
241
|
+
runId: string;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export interface ClientDeleteSessionMessage {
|
|
245
|
+
type: 'delete_session';
|
|
246
|
+
sessionId: string;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export interface ClientDeleteAllSessionsMessage {
|
|
250
|
+
type: 'delete_all_sessions';
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export type ClientMessage =
|
|
254
|
+
| ClientStartSessionMessage
|
|
255
|
+
| ClientSendMessage
|
|
256
|
+
| ClientCancelMessage
|
|
257
|
+
| ClientDeleteSessionMessage
|
|
258
|
+
| ClientDeleteAllSessionsMessage;
|
|
259
|
+
|
|
260
|
+
export function parseServerMessage(raw: unknown): ServerMessage | null {
|
|
261
|
+
if (typeof raw !== 'string' && (raw === null || typeof raw !== 'object')) {
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
const parsed = typeof raw === 'string' ? parseJson(raw) : raw;
|
|
265
|
+
if (parsed === null || typeof parsed !== 'object') {
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
const message = parsed as Record<string, unknown>;
|
|
269
|
+
const type = typeof message.type === 'string' ? message.type : '';
|
|
270
|
+
if (!type) {
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
switch (type) {
|
|
275
|
+
case 'cli_defaults':
|
|
276
|
+
const cliDefaultsMessage: ServerCliDefaultsMessage = {
|
|
277
|
+
type,
|
|
278
|
+
protocolVersion: typeof message.protocolVersion === 'string' ? message.protocolVersion : undefined
|
|
279
|
+
};
|
|
280
|
+
if (Object.prototype.hasOwnProperty.call(message, 'model')) {
|
|
281
|
+
cliDefaultsMessage.model =
|
|
282
|
+
typeof message.model === 'string' || message.model === null ? (message.model as string | null) : null;
|
|
283
|
+
}
|
|
284
|
+
if (Object.prototype.hasOwnProperty.call(message, 'reasoningEffort')) {
|
|
285
|
+
cliDefaultsMessage.reasoningEffort =
|
|
286
|
+
typeof message.reasoningEffort === 'string' || message.reasoningEffort === null
|
|
287
|
+
? (message.reasoningEffort as string | null)
|
|
288
|
+
: null;
|
|
289
|
+
}
|
|
290
|
+
if (Object.prototype.hasOwnProperty.call(message, 'availableModels')) {
|
|
291
|
+
cliDefaultsMessage.availableModels = parseModelCatalog(
|
|
292
|
+
Array.isArray(message.availableModels) ? message.availableModels : []
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
return cliDefaultsMessage;
|
|
296
|
+
case 'rate_limits':
|
|
297
|
+
return {
|
|
298
|
+
type,
|
|
299
|
+
protocolVersion: typeof message.protocolVersion === 'string' ? message.protocolVersion : undefined,
|
|
300
|
+
snapshot: message.snapshot ?? null
|
|
301
|
+
} as ServerRateLimitsMessage;
|
|
302
|
+
case 'delete_all_sessions':
|
|
303
|
+
if (
|
|
304
|
+
typeof message.ok !== 'boolean' ||
|
|
305
|
+
!Number.isFinite(Number(message.deletedCount)) ||
|
|
306
|
+
!Number.isFinite(Number(message.failedCount)) ||
|
|
307
|
+
typeof message.message !== 'string'
|
|
308
|
+
) {
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
return {
|
|
312
|
+
type,
|
|
313
|
+
protocolVersion: typeof message.protocolVersion === 'string' ? message.protocolVersion : undefined,
|
|
314
|
+
ok: message.ok,
|
|
315
|
+
deletedCount: Number(message.deletedCount),
|
|
316
|
+
failedCount: Number(message.failedCount),
|
|
317
|
+
message: message.message
|
|
318
|
+
} as ServerDeleteAllSessionsMessage;
|
|
319
|
+
case 'status':
|
|
320
|
+
return {
|
|
321
|
+
type,
|
|
322
|
+
protocolVersion: typeof message.protocolVersion === 'string' ? message.protocolVersion : undefined,
|
|
323
|
+
state: message.state === 'running' ? 'running' : 'ready',
|
|
324
|
+
runId: typeof message.runId === 'string' ? message.runId : undefined,
|
|
325
|
+
sessionId: typeof message.sessionId === 'string' ? message.sessionId : undefined,
|
|
326
|
+
sessionContextKey: typeof message.sessionContextKey === 'string' ? message.sessionContextKey : undefined,
|
|
327
|
+
notebookPath: typeof message.notebookPath === 'string' ? message.notebookPath : undefined,
|
|
328
|
+
runMode: message.runMode === 'fallback' ? 'fallback' : message.runMode === 'resume' ? 'resume' : undefined,
|
|
329
|
+
pairedOk: typeof message.pairedOk === 'boolean' ? message.pairedOk : undefined,
|
|
330
|
+
pairedPath: typeof message.pairedPath === 'string' ? message.pairedPath : undefined,
|
|
331
|
+
pairedOsPath: typeof message.pairedOsPath === 'string' ? message.pairedOsPath : undefined,
|
|
332
|
+
pairedMessage: typeof message.pairedMessage === 'string' ? message.pairedMessage : undefined,
|
|
333
|
+
notebookMode: typeof message.notebookMode === 'string' ? message.notebookMode : undefined,
|
|
334
|
+
sessionResolution: typeof message.sessionResolution === 'string' ? message.sessionResolution : undefined,
|
|
335
|
+
sessionResolutionNotice:
|
|
336
|
+
typeof message.sessionResolutionNotice === 'string' ? message.sessionResolutionNotice : undefined,
|
|
337
|
+
history: Array.isArray(message.history) ? (message.history as ServerStatusMessage['history']) : undefined,
|
|
338
|
+
effectiveSandbox: typeof message.effectiveSandbox === 'string' ? message.effectiveSandbox : undefined
|
|
339
|
+
};
|
|
340
|
+
case 'output':
|
|
341
|
+
if (
|
|
342
|
+
typeof message.runId !== 'string' ||
|
|
343
|
+
typeof message.sessionId !== 'string' ||
|
|
344
|
+
typeof message.notebookPath !== 'string' ||
|
|
345
|
+
typeof message.text !== 'string'
|
|
346
|
+
) {
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
return {
|
|
350
|
+
type,
|
|
351
|
+
protocolVersion: typeof message.protocolVersion === 'string' ? message.protocolVersion : undefined,
|
|
352
|
+
runId: message.runId,
|
|
353
|
+
sessionId: message.sessionId,
|
|
354
|
+
sessionContextKey: typeof message.sessionContextKey === 'string' ? message.sessionContextKey : undefined,
|
|
355
|
+
notebookPath: message.notebookPath,
|
|
356
|
+
role: typeof message.role === 'string' ? (message.role as 'user' | 'assistant' | 'system') : 'assistant',
|
|
357
|
+
text: message.text
|
|
358
|
+
};
|
|
359
|
+
case 'event':
|
|
360
|
+
if (
|
|
361
|
+
typeof message.runId !== 'string' ||
|
|
362
|
+
typeof message.sessionId !== 'string' ||
|
|
363
|
+
typeof message.notebookPath !== 'string'
|
|
364
|
+
) {
|
|
365
|
+
return null;
|
|
366
|
+
}
|
|
367
|
+
return {
|
|
368
|
+
type,
|
|
369
|
+
protocolVersion: typeof message.protocolVersion === 'string' ? message.protocolVersion : undefined,
|
|
370
|
+
runId: message.runId,
|
|
371
|
+
sessionId: message.sessionId,
|
|
372
|
+
sessionContextKey: typeof message.sessionContextKey === 'string' ? message.sessionContextKey : undefined,
|
|
373
|
+
notebookPath: message.notebookPath,
|
|
374
|
+
payload: message.payload
|
|
375
|
+
} as ServerEventMessage;
|
|
376
|
+
case 'done':
|
|
377
|
+
if (
|
|
378
|
+
typeof message.runId !== 'string' ||
|
|
379
|
+
typeof message.sessionId !== 'string' ||
|
|
380
|
+
typeof message.notebookPath !== 'string'
|
|
381
|
+
) {
|
|
382
|
+
return null;
|
|
383
|
+
}
|
|
384
|
+
let exitCode: number | null = null;
|
|
385
|
+
if (message.exitCode === null) {
|
|
386
|
+
exitCode = null;
|
|
387
|
+
} else if (typeof message.exitCode === 'number' && Number.isFinite(message.exitCode)) {
|
|
388
|
+
exitCode = message.exitCode;
|
|
389
|
+
} else if (typeof message.exitCode === 'string') {
|
|
390
|
+
const parsedExitCode = Number(message.exitCode.trim());
|
|
391
|
+
exitCode = Number.isFinite(parsedExitCode) ? parsedExitCode : null;
|
|
392
|
+
}
|
|
393
|
+
return {
|
|
394
|
+
type,
|
|
395
|
+
protocolVersion: typeof message.protocolVersion === 'string' ? message.protocolVersion : undefined,
|
|
396
|
+
runId: message.runId,
|
|
397
|
+
sessionId: message.sessionId,
|
|
398
|
+
sessionContextKey: typeof message.sessionContextKey === 'string' ? message.sessionContextKey : undefined,
|
|
399
|
+
notebookPath: message.notebookPath,
|
|
400
|
+
exitCode,
|
|
401
|
+
cancelled: typeof message.cancelled === 'boolean' ? message.cancelled : false,
|
|
402
|
+
fileChanged: typeof message.fileChanged === 'boolean' ? message.fileChanged : false,
|
|
403
|
+
runMode: message.runMode === 'fallback' ? 'fallback' : message.runMode === 'resume' ? 'resume' : undefined,
|
|
404
|
+
pairedOk: typeof message.pairedOk === 'boolean' ? message.pairedOk : undefined,
|
|
405
|
+
pairedPath: typeof message.pairedPath === 'string' ? message.pairedPath : undefined,
|
|
406
|
+
pairedOsPath: typeof message.pairedOsPath === 'string' ? message.pairedOsPath : undefined,
|
|
407
|
+
pairedMessage: typeof message.pairedMessage === 'string' ? message.pairedMessage : undefined,
|
|
408
|
+
notebookMode: typeof message.notebookMode === 'string' ? message.notebookMode : undefined
|
|
409
|
+
};
|
|
410
|
+
case 'error':
|
|
411
|
+
if (typeof message.message !== 'string') {
|
|
412
|
+
return null;
|
|
413
|
+
}
|
|
414
|
+
return {
|
|
415
|
+
type,
|
|
416
|
+
protocolVersion: typeof message.protocolVersion === 'string' ? message.protocolVersion : undefined,
|
|
417
|
+
runId: typeof message.runId === 'string' ? message.runId : undefined,
|
|
418
|
+
sessionId: typeof message.sessionId === 'string' ? message.sessionId : undefined,
|
|
419
|
+
sessionContextKey: typeof message.sessionContextKey === 'string' ? message.sessionContextKey : undefined,
|
|
420
|
+
notebookPath: typeof message.notebookPath === 'string' ? message.notebookPath : undefined,
|
|
421
|
+
message: message.message,
|
|
422
|
+
runMode: message.runMode === 'fallback' ? 'fallback' : message.runMode === 'resume' ? 'resume' : undefined,
|
|
423
|
+
suggestedCommandPath:
|
|
424
|
+
typeof message.suggestedCommandPath === 'string' ? message.suggestedCommandPath : undefined,
|
|
425
|
+
pairedOk: typeof message.pairedOk === 'boolean' ? message.pairedOk : undefined,
|
|
426
|
+
pairedPath: typeof message.pairedPath === 'string' ? message.pairedPath : undefined,
|
|
427
|
+
pairedOsPath: typeof message.pairedOsPath === 'string' ? message.pairedOsPath : undefined,
|
|
428
|
+
pairedMessage: typeof message.pairedMessage === 'string' ? message.pairedMessage : undefined,
|
|
429
|
+
notebookMode: typeof message.notebookMode === 'string' ? message.notebookMode : undefined
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
return null;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
export function parseModelCatalog(rawModels: unknown): ModelCatalogEntry[] {
|
|
436
|
+
if (!Array.isArray(rawModels)) {
|
|
437
|
+
return [];
|
|
438
|
+
}
|
|
439
|
+
const seen = new Set<string>();
|
|
440
|
+
const catalog: ModelCatalogEntry[] = [];
|
|
441
|
+
for (const item of rawModels) {
|
|
442
|
+
if (!item || typeof item !== 'object') {
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
const rawModel = (item as Record<string, unknown>).model;
|
|
446
|
+
const rawDisplayName = (item as Record<string, unknown>).displayName;
|
|
447
|
+
const rawReasoningEfforts =
|
|
448
|
+
(item as Record<string, unknown>).reasoningEfforts ??
|
|
449
|
+
(item as Record<string, unknown>).supportedReasoningEfforts;
|
|
450
|
+
const rawDefaultReasoningEffort = (item as Record<string, unknown>).defaultReasoningEffort;
|
|
451
|
+
if (typeof rawModel !== 'string') {
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
454
|
+
const model = rawModel.trim();
|
|
455
|
+
if (!model || seen.has(model)) {
|
|
456
|
+
continue;
|
|
457
|
+
}
|
|
458
|
+
seen.add(model);
|
|
459
|
+
const displayName =
|
|
460
|
+
typeof rawDisplayName === 'string' && rawDisplayName.trim() ? rawDisplayName.trim() : model;
|
|
461
|
+
const defaultReasoningEffort =
|
|
462
|
+
typeof rawDefaultReasoningEffort === 'string' && rawDefaultReasoningEffort.trim()
|
|
463
|
+
? rawDefaultReasoningEffort.trim()
|
|
464
|
+
: '';
|
|
465
|
+
|
|
466
|
+
const reasoningEfforts = Array.isArray(rawReasoningEfforts)
|
|
467
|
+
? rawReasoningEfforts.reduce<string[]>((acc, effortCandidate: unknown) => {
|
|
468
|
+
const effort = coerceReasoningEffortEntry(effortCandidate);
|
|
469
|
+
if (!effort || acc.includes(effort)) {
|
|
470
|
+
return acc;
|
|
471
|
+
}
|
|
472
|
+
acc.push(effort);
|
|
473
|
+
return acc;
|
|
474
|
+
}, [])
|
|
475
|
+
: [];
|
|
476
|
+
|
|
477
|
+
catalog.push({
|
|
478
|
+
model,
|
|
479
|
+
displayName,
|
|
480
|
+
...(reasoningEfforts.length > 0 ? { reasoningEfforts } : {}),
|
|
481
|
+
...(defaultReasoningEffort ? { defaultReasoningEffort } : {})
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
return catalog;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
export function buildStartSessionMessage(input: {
|
|
488
|
+
sessionId: string;
|
|
489
|
+
sessionContextKey: string;
|
|
490
|
+
notebookPath: string;
|
|
491
|
+
forceNewThread?: boolean;
|
|
492
|
+
commandPath?: string;
|
|
493
|
+
}): ClientStartSessionMessage {
|
|
494
|
+
return {
|
|
495
|
+
type: 'start_session',
|
|
496
|
+
sessionId: input.sessionId,
|
|
497
|
+
sessionContextKey: input.sessionContextKey,
|
|
498
|
+
notebookPath: input.notebookPath,
|
|
499
|
+
forceNewThread: input.forceNewThread === true,
|
|
500
|
+
commandPath: input.commandPath ? input.commandPath.trim() : undefined
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
export function buildSendMessage(input: {
|
|
505
|
+
sessionId: string;
|
|
506
|
+
sessionContextKey: string;
|
|
507
|
+
notebookPath: string;
|
|
508
|
+
commandPath: string;
|
|
509
|
+
content: string;
|
|
510
|
+
model: string;
|
|
511
|
+
reasoningEffort: string;
|
|
512
|
+
sandbox: string;
|
|
513
|
+
selection?: string;
|
|
514
|
+
cellOutput?: string;
|
|
515
|
+
images?: { name: string; dataUrl: string }[];
|
|
516
|
+
uiSelectionPreview?: unknown;
|
|
517
|
+
uiCellOutputPreview?: unknown;
|
|
518
|
+
selectionTruncated?: boolean;
|
|
519
|
+
cellOutputTruncated?: boolean;
|
|
520
|
+
}): ClientSendMessage {
|
|
521
|
+
return {
|
|
522
|
+
type: 'send',
|
|
523
|
+
sessionId: input.sessionId,
|
|
524
|
+
sessionContextKey: input.sessionContextKey,
|
|
525
|
+
notebookPath: input.notebookPath,
|
|
526
|
+
...(input.commandPath ? { commandPath: input.commandPath } : {}),
|
|
527
|
+
content: input.content,
|
|
528
|
+
model: input.model,
|
|
529
|
+
reasoningEffort: input.reasoningEffort,
|
|
530
|
+
sandbox: input.sandbox,
|
|
531
|
+
...(input.selection ? { selection: input.selection } : {}),
|
|
532
|
+
...(input.cellOutput ? { cellOutput: input.cellOutput } : {}),
|
|
533
|
+
...(input.images ? { images: input.images } : {}),
|
|
534
|
+
...(input.uiSelectionPreview ? { uiSelectionPreview: input.uiSelectionPreview } : {}),
|
|
535
|
+
...(input.uiCellOutputPreview ? { uiCellOutputPreview: input.uiCellOutputPreview } : {}),
|
|
536
|
+
...(input.selectionTruncated ? { selectionTruncated: true } : {}),
|
|
537
|
+
...(input.cellOutputTruncated ? { cellOutputTruncated: true } : {})
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
export function buildCancelMessage(runId: string): ClientCancelMessage {
|
|
542
|
+
return {
|
|
543
|
+
type: 'cancel',
|
|
544
|
+
runId
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
export function buildDeleteSessionMessage(sessionId: string): ClientDeleteSessionMessage {
|
|
549
|
+
return {
|
|
550
|
+
type: 'delete_session',
|
|
551
|
+
sessionId
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
export function buildDeleteAllSessionsMessage(): ClientDeleteAllSessionsMessage {
|
|
556
|
+
return {
|
|
557
|
+
type: 'delete_all_sessions'
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
function parseJson(raw: string): unknown | null {
|
|
562
|
+
try {
|
|
563
|
+
return JSON.parse(raw);
|
|
564
|
+
} catch {
|
|
565
|
+
return null;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
function coerceReasoningEffortEntry(value: unknown): string {
|
|
570
|
+
if (typeof value === 'string') {
|
|
571
|
+
return value.trim();
|
|
572
|
+
}
|
|
573
|
+
if (
|
|
574
|
+
value &&
|
|
575
|
+
typeof value === 'object' &&
|
|
576
|
+
'reasoningEffort' in (value as Record<string, unknown>)
|
|
577
|
+
) {
|
|
578
|
+
const candidate = (value as { reasoningEffort?: unknown }).reasoningEffort;
|
|
579
|
+
return typeof candidate === 'string' ? candidate.trim() : '';
|
|
580
|
+
}
|
|
581
|
+
return '';
|
|
582
|
+
}
|