@jskit-ai/assistant-core 0.1.165 → 0.1.166

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 (63) hide show
  1. package/examples/conversation/App.vue +104 -0
  2. package/examples/conversation/README.md +42 -0
  3. package/examples/conversation/dist/assets/index-CSTXm6q3.css +1 -0
  4. package/examples/conversation/dist/assets/index-DGgOLzoo.js +30 -0
  5. package/examples/conversation/dist/index.html +4 -0
  6. package/examples/conversation/index.html +2 -0
  7. package/examples/conversation/main.js +9 -0
  8. package/examples/conversation/node_modules/.vite/deps/@mdi_js.js +7450 -0
  9. package/examples/conversation/node_modules/.vite/deps/@mdi_js.js.map +1 -0
  10. package/examples/conversation/node_modules/.vite/deps/VTooltip-jIxO6ULs.js +2311 -0
  11. package/examples/conversation/node_modules/.vite/deps/VTooltip-jIxO6ULs.js.map +1 -0
  12. package/examples/conversation/node_modules/.vite/deps/_metadata.json +70 -0
  13. package/examples/conversation/node_modules/.vite/deps/defineComponent-DK6LSjDW.js +710 -0
  14. package/examples/conversation/node_modules/.vite/deps/defineComponent-DK6LSjDW.js.map +1 -0
  15. package/examples/conversation/node_modules/.vite/deps/hotkey-parsing-DnoZxtbW.js +1214 -0
  16. package/examples/conversation/node_modules/.vite/deps/hotkey-parsing-DnoZxtbW.js.map +1 -0
  17. package/examples/conversation/node_modules/.vite/deps/icons-ze2hmg7j.js +98 -0
  18. package/examples/conversation/node_modules/.vite/deps/icons-ze2hmg7j.js.map +1 -0
  19. package/examples/conversation/node_modules/.vite/deps/package.json +3 -0
  20. package/examples/conversation/node_modules/.vite/deps/theme-D78LVcJg.js +1301 -0
  21. package/examples/conversation/node_modules/.vite/deps/theme-D78LVcJg.js.map +1 -0
  22. package/examples/conversation/node_modules/.vite/deps/vue.js +2 -0
  23. package/examples/conversation/node_modules/.vite/deps/vue.runtime.esm-bundler-YcakWsDn.js +8538 -0
  24. package/examples/conversation/node_modules/.vite/deps/vue.runtime.esm-bundler-YcakWsDn.js.map +1 -0
  25. package/examples/conversation/node_modules/.vite/deps/vuetify.js +413 -0
  26. package/examples/conversation/node_modules/.vite/deps/vuetify.js.map +1 -0
  27. package/examples/conversation/node_modules/.vite/deps/vuetify_components.js +25370 -0
  28. package/examples/conversation/node_modules/.vite/deps/vuetify_components.js.map +1 -0
  29. package/examples/conversation/node_modules/.vite/deps/vuetify_directives.js +132 -0
  30. package/examples/conversation/node_modules/.vite/deps/vuetify_directives.js.map +1 -0
  31. package/examples/conversation/node_modules/.vite/deps/vuetify_iconsets_mdi-svg.js +70 -0
  32. package/examples/conversation/node_modules/.vite/deps/vuetify_iconsets_mdi-svg.js.map +1 -0
  33. package/examples/conversation/package.json +22 -0
  34. package/examples/conversation/server.js +123 -0
  35. package/examples/conversation/vite.config.js +8 -0
  36. package/package.json +59 -7
  37. package/src/client/conversation/AssistantComposerActions.vue +43 -0
  38. package/src/client/conversation/AssistantConversationElement.vue +78 -0
  39. package/src/client/conversation/AssistantProgress.vue +88 -0
  40. package/src/client/conversation/AssistantPromptInput.vue +467 -0
  41. package/src/client/conversation/AssistantTranscript.vue +1361 -0
  42. package/src/client/conversation/LongTextInlineParts.vue +64 -0
  43. package/src/client/conversation/LongTextPreviewBlocks.vue +324 -0
  44. package/src/client/conversation/index.js +9 -0
  45. package/src/client/conversation/submitText.js +29 -0
  46. package/src/client/conversation/useScrollToBottom.js +151 -0
  47. package/src/server/conversation/codexClient.js +328 -0
  48. package/src/server/conversation/codexEvents.js +623 -0
  49. package/src/server/conversation/codexTurn.js +280 -0
  50. package/src/server/conversation/index.js +2 -0
  51. package/src/server/conversation/memoryStorage.js +76 -0
  52. package/src/server/conversation/normalize.js +7 -0
  53. package/src/server/conversation/openCodeClient.js +512 -0
  54. package/src/server/conversation/transcript.js +92 -0
  55. package/src/shared/conversation/answerChoiceSugar.js +191 -0
  56. package/src/shared/conversation/index.js +6 -0
  57. package/src/shared/conversation/longTextBlocks.js +403 -0
  58. package/src/shared/conversation/numberedQuestionSugar.js +295 -0
  59. package/src/shared/conversation/scrollFollowState.js +32 -0
  60. package/src/shared/conversation/thinkingText.js +13 -0
  61. package/src/shared/conversation/turns.js +30 -0
  62. package/src/testing/conversationStorageContract.js +35 -0
  63. package/test/conversation.test.js +57 -0
@@ -0,0 +1,623 @@
1
+ import {
2
+ isPlainObject,
3
+ normalizeText
4
+ } from "./normalize.js";
5
+
6
+ const CODEX_APP_SERVER_CONTEXT_COMPACTION_SIGNALS = new Set(
7
+ [
8
+ "contextcompaction",
9
+ ...["context", "thread", "conversation"].flatMap((subject) => (
10
+ ["compact", "compacted", "compaction", "truncate", "truncated", "truncation"]
11
+ .flatMap((state) => [`${subject}_${state}`, `${state}_${subject}`])
12
+ ))
13
+ ]
14
+ );
15
+ const CODEX_APP_SERVER_CONTEXT_REFRESH_SIGNALS = new Set([
16
+ "context_refresh_required",
17
+ "context_refresh_needed",
18
+ "context_refresh_pending"
19
+ ]);
20
+
21
+ function codexAppServerStatusFromValue(status = null) {
22
+ if (typeof status === "string") {
23
+ const normalized = normalizeText(status);
24
+ if (normalized === "active") {
25
+ return "inProgress";
26
+ }
27
+ if (normalized === "idle" || normalized === "notLoaded") {
28
+ return "completed";
29
+ }
30
+ if (normalized === "systemError") {
31
+ return "failed";
32
+ }
33
+ return normalized;
34
+ }
35
+ if (!isPlainObject(status)) {
36
+ return "";
37
+ }
38
+ const type = normalizeText(status.type);
39
+ if (type === "active") {
40
+ return "inProgress";
41
+ }
42
+ if (type === "idle" || type === "notLoaded" || type === "completed") {
43
+ return "completed";
44
+ }
45
+ if (type === "systemError" || type === "failed") {
46
+ return "failed";
47
+ }
48
+ if (type === "interrupted") {
49
+ return "interrupted";
50
+ }
51
+ return type;
52
+ }
53
+
54
+ function codexAppServerNotificationParams(notification = {}) {
55
+ return isPlainObject(notification?.params) ? notification.params : {};
56
+ }
57
+
58
+ function codexAppServerNotificationEvent(notification = {}) {
59
+ const method = normalizeText(notification.method);
60
+ const params = codexAppServerNotificationParams(notification);
61
+ const candidates = [
62
+ params.event,
63
+ params.msg,
64
+ params.entry,
65
+ params.record,
66
+ notification.event,
67
+ notification.msg,
68
+ notification.entry,
69
+ notification.record
70
+ ];
71
+ for (const candidate of candidates) {
72
+ if (isPlainObject(candidate)) {
73
+ return candidate;
74
+ }
75
+ }
76
+ if (isPlainObject(params.payload) || normalizeText(params.type)) {
77
+ return params;
78
+ }
79
+ if (isPlainObject(notification.payload) || normalizeText(notification.type)) {
80
+ return notification;
81
+ }
82
+ if (["event_msg", "response_item", "task_complete"].includes(method) && isPlainObject(params)) {
83
+ return params;
84
+ }
85
+ return null;
86
+ }
87
+
88
+ function codexAppServerNotificationEventType(notification = {}, event = null) {
89
+ const params = codexAppServerNotificationParams(notification);
90
+ return normalizeText(event?.type || params.type || notification.type || notification.method);
91
+ }
92
+
93
+ function codexAppServerNotificationEventPayload(notification = {}, event = null) {
94
+ if (isPlainObject(event?.payload)) {
95
+ return event.payload;
96
+ }
97
+ const params = codexAppServerNotificationParams(notification);
98
+ if (isPlainObject(params.payload)) {
99
+ return params.payload;
100
+ }
101
+ if (isPlainObject(notification.payload)) {
102
+ return notification.payload;
103
+ }
104
+ return isPlainObject(event) ? event : {};
105
+ }
106
+
107
+ function codexAppServerNotificationItem(notification = {}) {
108
+ const item = codexAppServerNotificationParams(notification).item;
109
+ return isPlainObject(item) ? item : null;
110
+ }
111
+
112
+ function codexAppServerNotificationThreadId(notification = {}) {
113
+ const params = codexAppServerNotificationParams(notification);
114
+ const event = codexAppServerNotificationEvent(notification);
115
+ const payload = codexAppServerNotificationEventPayload(notification, event);
116
+ return normalizeText(
117
+ params.threadId ||
118
+ params.thread_id ||
119
+ params.thread?.id ||
120
+ event?.threadId ||
121
+ event?.thread_id ||
122
+ payload.threadId ||
123
+ payload.thread_id
124
+ );
125
+ }
126
+
127
+ function codexAppServerNotificationTurnId(notification = {}) {
128
+ const params = codexAppServerNotificationParams(notification);
129
+ const event = codexAppServerNotificationEvent(notification);
130
+ const payload = codexAppServerNotificationEventPayload(notification, event);
131
+ const item = codexAppServerNotificationItem(notification);
132
+ return normalizeText(
133
+ params.turnId ||
134
+ params.turn_id ||
135
+ params.turn?.id ||
136
+ event?.turnId ||
137
+ event?.turn_id ||
138
+ payload.turnId ||
139
+ payload.turn_id ||
140
+ item?.turnId ||
141
+ item?.turn_id
142
+ );
143
+ }
144
+
145
+ function codexAppServerNotificationTurnStatus(notification = {}) {
146
+ const params = codexAppServerNotificationParams(notification);
147
+ const turnStatus = normalizeText(params.turn?.status);
148
+ return turnStatus || codexAppServerStatusFromValue(params.status);
149
+ }
150
+
151
+ function codexAppServerErrorText(value = null, seen = new Set()) {
152
+ if (!value) {
153
+ return "";
154
+ }
155
+ if (typeof value === "string") {
156
+ const text = normalizeText(value);
157
+ if (text.startsWith("{") || text.startsWith("[")) {
158
+ try {
159
+ const parsed = JSON.parse(text);
160
+ const parsedText = codexAppServerErrorText(parsed, seen);
161
+ if (parsedText) {
162
+ return parsedText;
163
+ }
164
+ } catch {
165
+ // Keep non-JSON provider details as their original user-facing text.
166
+ }
167
+ }
168
+ return text;
169
+ }
170
+ if (!isPlainObject(value)) {
171
+ return "";
172
+ }
173
+ if (seen.has(value)) {
174
+ return "";
175
+ }
176
+ seen.add(value);
177
+ const messages = [
178
+ codexAppServerErrorText(value.message, seen),
179
+ codexAppServerErrorText(value.error, seen),
180
+ codexAppServerErrorText(value.additionalDetails || value.additional_details, seen),
181
+ codexAppServerErrorText(value.details || value.detail, seen),
182
+ codexAppServerErrorText(value.reason, seen),
183
+ codexAppServerErrorText(value.codexErrorInfo || value.codex_error_info, seen)
184
+ ].filter(Boolean);
185
+ if (!messages.length) {
186
+ return normalizeText(value.code);
187
+ }
188
+ return [...new Set(messages)].join(" ");
189
+ }
190
+
191
+ function codexAppServerNotificationError(notification = {}) {
192
+ const params = codexAppServerNotificationParams(notification);
193
+ const status = isPlainObject(params.status) ? params.status : {};
194
+ const turn = isPlainObject(params.turn) ? params.turn : {};
195
+ return normalizeText(
196
+ codexAppServerErrorText(params.error) ||
197
+ params.message ||
198
+ codexAppServerErrorText(status.error) ||
199
+ status.message ||
200
+ codexAppServerErrorText(turn.error) ||
201
+ turn.message
202
+ );
203
+ }
204
+
205
+ function codexAppServerNotificationUsageLimitExceeded(notification = {}) {
206
+ const params = codexAppServerNotificationParams(notification);
207
+ const status = isPlainObject(params.status) ? params.status : {};
208
+ const turn = isPlainObject(params.turn) ? params.turn : {};
209
+ return [params.error, status.error, turn.error].some((error) => (
210
+ isPlainObject(error) &&
211
+ normalizeText(error.codexErrorInfo || error.codex_error_info) === "usageLimitExceeded"
212
+ ));
213
+ }
214
+
215
+ function codexAppServerTextInputText(input = {}) {
216
+ if (!isPlainObject(input) || normalizeText(input.type) !== "text") {
217
+ return "";
218
+ }
219
+ return normalizeText(input.text);
220
+ }
221
+
222
+ function codexAppServerUserMessageText(item = {}) {
223
+ if (!isPlainObject(item) || normalizeText(item.type) !== "userMessage") {
224
+ return "";
225
+ }
226
+ return (Array.isArray(item.content) ? item.content : [])
227
+ .map((input) => codexAppServerTextInputText(input))
228
+ .filter(Boolean)
229
+ .join("\n\n");
230
+ }
231
+
232
+ function codexAppServerContentText(value = null) {
233
+ if (typeof value === "string") {
234
+ return value;
235
+ }
236
+ if (Array.isArray(value)) {
237
+ return value.map((entry) => codexAppServerContentText(entry)).filter(Boolean).join("");
238
+ }
239
+ if (!isPlainObject(value)) {
240
+ return "";
241
+ }
242
+ if (typeof value.text === "string") {
243
+ return value.text;
244
+ }
245
+ if (typeof value.value === "string") {
246
+ return value.value;
247
+ }
248
+ if (typeof value.content === "string" || Array.isArray(value.content)) {
249
+ return codexAppServerContentText(value.content);
250
+ }
251
+ if (typeof value.message === "string" || Array.isArray(value.message)) {
252
+ return codexAppServerContentText(value.message);
253
+ }
254
+ if (isPlainObject(value.message)) {
255
+ return codexAppServerContentText(value.message.content || value.message.text);
256
+ }
257
+ return "";
258
+ }
259
+
260
+ function codexAppServerAssistantItemText(item = {}) {
261
+ if (!isPlainObject(item)) {
262
+ return "";
263
+ }
264
+ const type = normalizeText(item.type);
265
+ const role = normalizeText(item.role || item.author?.role);
266
+ const isAssistant = role === "assistant" ||
267
+ type === "agentMessage" ||
268
+ type === "assistantMessage" ||
269
+ type === "assistant_message" ||
270
+ type === "outputMessage" ||
271
+ type === "message" && role === "assistant";
272
+ if (!isAssistant) {
273
+ return "";
274
+ }
275
+ return normalizeText(
276
+ codexAppServerContentText(item.content) ||
277
+ codexAppServerContentText(item.text) ||
278
+ codexAppServerContentText(item.message)
279
+ );
280
+ }
281
+
282
+ function codexAppServerHookPromptText(item = {}) {
283
+ if (!isPlainObject(item) || normalizeText(item.type) !== "hookPrompt") {
284
+ return "";
285
+ }
286
+ return (Array.isArray(item.fragments) ? item.fragments : [])
287
+ .map((fragment) => normalizeText(fragment?.text))
288
+ .filter(Boolean)
289
+ .join("\n\n");
290
+ }
291
+
292
+ function codexAppServerNotificationItemId(notification = {}) {
293
+ const params = codexAppServerNotificationParams(notification);
294
+ const item = codexAppServerNotificationItem(notification);
295
+ const event = codexAppServerNotificationEvent(notification);
296
+ const payload = codexAppServerNotificationEventPayload(notification, event);
297
+ return normalizeText(
298
+ item?.id ||
299
+ params.itemId ||
300
+ params.item_id ||
301
+ event?.itemId ||
302
+ event?.item_id ||
303
+ payload.itemId ||
304
+ payload.item_id ||
305
+ payload.id
306
+ );
307
+ }
308
+
309
+ function codexAppServerFinalEventText(notification = {}, event = null, payload = {}) {
310
+ const eventType = codexAppServerNotificationEventType(notification, event);
311
+ const payloadType = normalizeText(payload.type);
312
+ const phase = normalizeText(payload.phase || event?.phase);
313
+ if (eventType === "task_complete") {
314
+ return normalizeText(
315
+ codexAppServerContentText(payload.last_agent_message) ||
316
+ codexAppServerContentText(payload.lastAgentMessage)
317
+ );
318
+ }
319
+ if (eventType === "event_msg" && payloadType === "agent_message" && phase === "final_answer") {
320
+ return normalizeText(
321
+ codexAppServerContentText(payload.message) ||
322
+ codexAppServerContentText(payload.text) ||
323
+ codexAppServerContentText(payload.content)
324
+ );
325
+ }
326
+ if (eventType === "response_item" && phase === "final_answer") {
327
+ return codexAppServerAssistantItemText(payload);
328
+ }
329
+ return "";
330
+ }
331
+
332
+ function classifyCodexAppServerEvent(notification = {}) {
333
+ const method = normalizeText(notification.method);
334
+ const event = codexAppServerNotificationEvent(notification);
335
+ const payload = codexAppServerNotificationEventPayload(notification, event);
336
+ const eventType = event ? codexAppServerNotificationEventType(notification, event) : "";
337
+ const payloadType = normalizeText(payload.type);
338
+ const item = codexAppServerNotificationItem(notification);
339
+ const itemType = normalizeText(item?.type);
340
+ const itemText = codexAppServerAssistantItemText(item);
341
+ const phase = normalizeText(payload.phase || event?.phase || item?.phase || item?.purpose || item?.category);
342
+ const base = {
343
+ itemId: codexAppServerNotificationItemId(notification),
344
+ source: method || eventType || "notification",
345
+ text: "",
346
+ threadId: codexAppServerNotificationThreadId(notification),
347
+ turnId: codexAppServerNotificationTurnId(notification)
348
+ };
349
+
350
+ if (method === "error") {
351
+ return {
352
+ ...base,
353
+ kind: "provider_error",
354
+ text: codexAppServerNotificationError(notification)
355
+ };
356
+ }
357
+
358
+ if (method === "item/reasoning/summaryPartAdded" || method === "item/reasoning/summaryTextDelta") {
359
+ return {
360
+ ...base,
361
+ kind: "reasoning_summary",
362
+ text: normalizeText(codexAppServerContentText(codexAppServerNotificationParams(notification).delta))
363
+ };
364
+ }
365
+
366
+ const finalEventText = event ? codexAppServerFinalEventText(notification, event, payload) : "";
367
+ if (finalEventText) {
368
+ return {
369
+ ...base,
370
+ kind: "final_assistant_result",
371
+ source: eventType,
372
+ text: finalEventText
373
+ };
374
+ }
375
+
376
+ if (itemType === "hookPrompt") {
377
+ return {
378
+ ...base,
379
+ kind: "hook_prompt",
380
+ text: codexAppServerHookPromptText(item)
381
+ };
382
+ }
383
+
384
+ if (method === "item/completed" && itemType === "userMessage") {
385
+ return {
386
+ ...base,
387
+ kind: "terminal_user_message",
388
+ text: codexAppServerUserMessageText(item)
389
+ };
390
+ }
391
+
392
+ if (method === "item/completed" && itemText) {
393
+ return phase === "final_answer"
394
+ ? {
395
+ ...base,
396
+ kind: "final_assistant_result",
397
+ source: "item",
398
+ text: itemText
399
+ }
400
+ : {
401
+ ...base,
402
+ kind: "live_progress",
403
+ source: "item",
404
+ text: itemText
405
+ };
406
+ }
407
+
408
+ if (eventType === "event_msg" && payloadType === "agent_message") {
409
+ if (!phase) {
410
+ return {
411
+ ...base,
412
+ kind: "ignored",
413
+ source: eventType
414
+ };
415
+ }
416
+ return {
417
+ ...base,
418
+ kind: "live_progress",
419
+ source: eventType,
420
+ text: normalizeText(
421
+ codexAppServerContentText(payload.message) ||
422
+ codexAppServerContentText(payload.text) ||
423
+ codexAppServerContentText(payload.content)
424
+ )
425
+ };
426
+ }
427
+
428
+ if (eventType === "response_item") {
429
+ if (!phase) {
430
+ return {
431
+ ...base,
432
+ kind: "ignored",
433
+ source: eventType
434
+ };
435
+ }
436
+ return {
437
+ ...base,
438
+ kind: "live_progress",
439
+ source: eventType,
440
+ text: codexAppServerAssistantItemText(payload)
441
+ };
442
+ }
443
+
444
+ if (method === "turn/started" || method === "turn/completed" || method === "thread/status/changed") {
445
+ return {
446
+ ...base,
447
+ kind: "status",
448
+ text: codexAppServerNotificationTurnStatus(notification)
449
+ };
450
+ }
451
+
452
+ return {
453
+ ...base,
454
+ kind: "ignored"
455
+ };
456
+ }
457
+
458
+ function codexAppServerSignalName(value = "") {
459
+ return normalizeText(value)
460
+ .toLowerCase()
461
+ .replaceAll("-", "_")
462
+ .replaceAll("/", "_");
463
+ }
464
+
465
+ function codexAppServerSignalNames(value = null) {
466
+ if (!value) {
467
+ return [];
468
+ }
469
+ if (typeof value === "string") {
470
+ return [codexAppServerSignalName(value)].filter(Boolean);
471
+ }
472
+ if (Array.isArray(value)) {
473
+ return value.flatMap((entry) => codexAppServerSignalNames(entry));
474
+ }
475
+ if (!isPlainObject(value)) {
476
+ return [];
477
+ }
478
+ return [
479
+ value.type,
480
+ value.event,
481
+ value.kind,
482
+ value.reason,
483
+ value.code,
484
+ value.status,
485
+ value.phase,
486
+ value.name
487
+ ].map((signal) => codexAppServerSignalName(signal)).filter(Boolean);
488
+ }
489
+
490
+ function codexAppServerContextRefreshReason(notification = {}) {
491
+ const method = normalizeText(notification.method);
492
+ const item = codexAppServerNotificationItem(notification);
493
+ const event = codexAppServerNotificationEvent(notification);
494
+ const payload = codexAppServerNotificationEventPayload(notification, event);
495
+ const eventType = codexAppServerNotificationEventType(notification, event);
496
+ const payloadType = normalizeText(payload.type);
497
+ const signals = [
498
+ method,
499
+ item?.type,
500
+ eventType,
501
+ payloadType,
502
+ ...codexAppServerSignalNames(item),
503
+ ...codexAppServerSignalNames(payload),
504
+ ...codexAppServerSignalNames(event)
505
+ ].map((signal) => codexAppServerSignalName(signal)).filter(Boolean);
506
+
507
+ if (signals.some((signal) => CODEX_APP_SERVER_CONTEXT_COMPACTION_SIGNALS.has(signal))) {
508
+ return "context_compacted";
509
+ }
510
+ if (signals.some((signal) => CODEX_APP_SERVER_CONTEXT_REFRESH_SIGNALS.has(signal))) {
511
+ return "context_refresh_required";
512
+ }
513
+ return "";
514
+ }
515
+
516
+ function codexAppServerProviderThread(value = {}) {
517
+ if (isPlainObject(value?.raw)) {
518
+ return value.raw;
519
+ }
520
+ if (isPlainObject(value?.response?.thread)) {
521
+ return value.response.thread;
522
+ }
523
+ if (isPlainObject(value?.thread)) {
524
+ return value.thread;
525
+ }
526
+ return isPlainObject(value) ? value : {};
527
+ }
528
+
529
+ function codexAppServerProviderTurnId(turn = {}) {
530
+ return normalizeText(turn.id || turn.turnId || turn.turn_id || turn.turn?.id);
531
+ }
532
+
533
+ function codexAppServerProviderTurnItems(turn = {}) {
534
+ return [
535
+ ...(Array.isArray(turn.items) ? turn.items : []),
536
+ ...(Array.isArray(turn.itemsView) ? turn.itemsView : [])
537
+ ].filter(isPlainObject);
538
+ }
539
+
540
+ function codexAppServerProviderThreadTurn(value = {}, turnId = "") {
541
+ const normalizedTurnId = normalizeText(turnId);
542
+ if (!normalizedTurnId) {
543
+ return null;
544
+ }
545
+ const thread = codexAppServerProviderThread(value);
546
+ return (Array.isArray(thread.turns) ? thread.turns : [])
547
+ .find((turn) => codexAppServerProviderTurnId(turn) === normalizedTurnId) || null;
548
+ }
549
+
550
+ function codexAppServerProviderTurnAssistantSegments(turn = {}) {
551
+ const seenItemIds = new Set();
552
+ return codexAppServerProviderTurnItems(turn)
553
+ .filter((item) => {
554
+ const phase = normalizeText(item.phase);
555
+ return !phase || phase === "final_answer";
556
+ })
557
+ .map((item) => {
558
+ const itemId = normalizeText(item.id);
559
+ const text = codexAppServerAssistantItemText(item);
560
+ if (
561
+ !itemId ||
562
+ !text ||
563
+ seenItemIds.has(itemId)
564
+ ) {
565
+ return null;
566
+ }
567
+ seenItemIds.add(itemId);
568
+ return {
569
+ itemId,
570
+ text
571
+ };
572
+ })
573
+ .filter(Boolean);
574
+ }
575
+
576
+ function codexAppServerProviderThreadAssistantSegments(value = {}, turnId = "") {
577
+ const turn = codexAppServerProviderThreadTurn(value, turnId);
578
+ return turn ? codexAppServerProviderTurnAssistantSegments(turn) : [];
579
+ }
580
+
581
+ function codexAppServerOutputOwnerTurnId({
582
+ notificationThreadId = "",
583
+ notificationTurnId = "",
584
+ trackedActive = false,
585
+ trackedState = "",
586
+ trackedThreadId = "",
587
+ trackedTurnId = ""
588
+ } = {}) {
589
+ const normalizedNotificationThreadId = normalizeText(notificationThreadId);
590
+ const normalizedTrackedThreadId = normalizeText(trackedThreadId);
591
+ const normalizedTrackedTurnId = normalizeText(trackedTurnId);
592
+ const trackedTurnOwnsResult = trackedActive === true &&
593
+ ["active", "finalizing"].includes(normalizeText(trackedState)) &&
594
+ Boolean(normalizedTrackedTurnId) &&
595
+ Boolean(normalizedNotificationThreadId) &&
596
+ normalizedNotificationThreadId === normalizedTrackedThreadId;
597
+ return trackedTurnOwnsResult
598
+ ? normalizedTrackedTurnId
599
+ : normalizeText(notificationTurnId);
600
+ }
601
+
602
+ export {
603
+ classifyCodexAppServerEvent,
604
+ codexAppServerAssistantItemText,
605
+ codexAppServerContentText,
606
+ codexAppServerContextRefreshReason,
607
+ codexAppServerErrorText,
608
+ codexAppServerNotificationError,
609
+ codexAppServerNotificationEvent,
610
+ codexAppServerNotificationEventPayload,
611
+ codexAppServerNotificationEventType,
612
+ codexAppServerNotificationItem,
613
+ codexAppServerNotificationItemId,
614
+ codexAppServerNotificationParams,
615
+ codexAppServerNotificationThreadId,
616
+ codexAppServerNotificationTurnId,
617
+ codexAppServerNotificationTurnStatus,
618
+ codexAppServerNotificationUsageLimitExceeded,
619
+ codexAppServerProviderThreadAssistantSegments,
620
+ codexAppServerOutputOwnerTurnId,
621
+ codexAppServerStatusFromValue,
622
+ codexAppServerUserMessageText
623
+ };