pi-openai-toolkit 0.14.13 → 0.15.1
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/README.md +250 -241
- package/README.zh.md +250 -241
- package/config.schema.json +352 -0
- package/docs/configuration.md +176 -0
- package/docs/internals.md +139 -128
- package/package.json +135 -127
- package/src/auto-mode/extension.ts +35 -13
- package/src/config/legacy.ts +717 -0
- package/src/config/migration.ts +100 -0
- package/src/config/notifications.ts +28 -0
- package/src/config/policy.ts +122 -0
- package/src/config/v2.ts +1347 -0
- package/src/config-command.ts +73 -0
- package/src/config.ts +318 -739
- package/src/context-management/tools.ts +353 -347
- package/src/context-management/window-manager.ts +696 -693
- package/src/debug.ts +5 -5
- package/src/deferred-tool-carryover.ts +3 -1
- package/src/extension-runtime.ts +1375 -1329
- package/src/image-generation/extension.ts +14 -18
- package/src/image-generation/protocol.ts +10 -4
- package/src/image-generation/service.ts +9 -3
- package/src/request-context-cache.ts +2 -1
- package/src/types.ts +641 -628
- package/src/web-search/alpha-client.ts +876 -875
- package/src/web-search/extension.ts +529 -523
- package/src/web-search/payload.ts +299 -295
- package/src/web-search/prompt.ts +60 -59
- package/src/web-search/types.ts +144 -144
|
@@ -1,875 +1,876 @@
|
|
|
1
|
-
import { StringEnum, Type, type Static } from "@earendil-works/pi-ai";
|
|
2
|
-
import { buildResponsesRequestHeaders } from "../responses-headers";
|
|
3
|
-
import { buildAlphaSearchUrl, type ResponsesRuntime } from "../runtime";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export const
|
|
7
|
-
export const
|
|
8
|
-
export const
|
|
9
|
-
export const
|
|
10
|
-
export const
|
|
11
|
-
export const
|
|
12
|
-
export const
|
|
13
|
-
export const
|
|
14
|
-
export const
|
|
15
|
-
export const
|
|
16
|
-
export const
|
|
17
|
-
export const
|
|
18
|
-
export const
|
|
19
|
-
export const
|
|
20
|
-
export const
|
|
21
|
-
export const
|
|
22
|
-
export const
|
|
23
|
-
export const
|
|
24
|
-
export const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
export type
|
|
161
|
-
export type
|
|
162
|
-
export type
|
|
163
|
-
export type
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
| "
|
|
250
|
-
| "
|
|
251
|
-
| "invalid-
|
|
252
|
-
| "
|
|
253
|
-
| "
|
|
254
|
-
| "
|
|
255
|
-
| "
|
|
256
|
-
| "
|
|
257
|
-
| "
|
|
258
|
-
| "
|
|
259
|
-
| "
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
| {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
if (trimmed
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
if (
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
if (trimmed
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
if (
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
if (
|
|
347
|
-
if (value
|
|
348
|
-
if (value.length
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
const
|
|
362
|
-
const
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
...(
|
|
367
|
-
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
if (
|
|
377
|
-
if (value
|
|
378
|
-
if (value.length
|
|
379
|
-
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
const
|
|
387
|
-
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
const
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
...(
|
|
437
|
-
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
const
|
|
445
|
-
const
|
|
446
|
-
const
|
|
447
|
-
const
|
|
448
|
-
const
|
|
449
|
-
const
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
...(
|
|
456
|
-
...(
|
|
457
|
-
...(
|
|
458
|
-
...(
|
|
459
|
-
...(
|
|
460
|
-
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
"
|
|
474
|
-
"
|
|
475
|
-
"
|
|
476
|
-
"
|
|
477
|
-
"
|
|
478
|
-
"
|
|
479
|
-
"
|
|
480
|
-
"
|
|
481
|
-
"
|
|
482
|
-
"
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
const
|
|
487
|
-
const
|
|
488
|
-
const
|
|
489
|
-
const
|
|
490
|
-
const
|
|
491
|
-
const
|
|
492
|
-
const
|
|
493
|
-
const
|
|
494
|
-
const
|
|
495
|
-
const
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
...(
|
|
503
|
-
...(
|
|
504
|
-
...(
|
|
505
|
-
...(
|
|
506
|
-
...(
|
|
507
|
-
...(
|
|
508
|
-
...(
|
|
509
|
-
...(
|
|
510
|
-
...(
|
|
511
|
-
...(
|
|
512
|
-
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
const
|
|
531
|
-
const
|
|
532
|
-
const
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
!Number.
|
|
537
|
-
maxOutputTokens
|
|
538
|
-
maxOutputTokens
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
const
|
|
558
|
-
|
|
559
|
-
.replace(/
|
|
560
|
-
.replace(/((?:api[-_ ]?key|access[_-]?token|access[_-]?key|client[_-]?secret|token|secret|password|cookie|authorization)\s*[
|
|
561
|
-
.replace(/(
|
|
562
|
-
.
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
const
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
return "
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
const
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
if (
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
offset
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
| { ok:
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
...(
|
|
702
|
-
...(
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
errorMessage,
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
const
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
//
|
|
751
|
-
//
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
return {
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
1
|
+
import { StringEnum, Type, type Static } from "@earendil-works/pi-ai";
|
|
2
|
+
import { buildResponsesRequestHeaders } from "../responses-headers";
|
|
3
|
+
import { buildAlphaSearchUrl, type ResponsesRuntime } from "../runtime";
|
|
4
|
+
import { WEB_RUN_TOOL_NAME } from "./types";
|
|
5
|
+
|
|
6
|
+
export const MAX_ALPHA_ACTIONS = 8;
|
|
7
|
+
export const MAX_ALPHA_COMMAND_CHARS = 4_096;
|
|
8
|
+
export const MAX_ALPHA_REF_ID_CHARS = 1_024;
|
|
9
|
+
export const MAX_ALPHA_DOMAIN_CHARS = 256;
|
|
10
|
+
export const MAX_ALPHA_DOMAINS = 16;
|
|
11
|
+
export const MAX_ALPHA_RECENCY_DAYS = 3_650;
|
|
12
|
+
export const MAX_ALPHA_LINE_NUMBER = 1_000_000;
|
|
13
|
+
export const MAX_ALPHA_LINK_ID = 10_000;
|
|
14
|
+
export const MAX_ALPHA_PAGE_NUMBER = 1_000_000;
|
|
15
|
+
export const MAX_ALPHA_WEATHER_DAYS = 31;
|
|
16
|
+
export const MAX_ALPHA_GAMES = 50;
|
|
17
|
+
export const MAX_ALPHA_REQUEST_BYTES = 64 * 1024;
|
|
18
|
+
export const MAX_ALPHA_RESPONSE_BYTES = 512 * 1024;
|
|
19
|
+
export const MAX_ALPHA_OUTPUT_BYTES = 64 * 1024;
|
|
20
|
+
export const MAX_ALPHA_RESULTS = 50;
|
|
21
|
+
export const MAX_ALPHA_RESULTS_BYTES = 256 * 1024;
|
|
22
|
+
export const MAX_ALPHA_ERROR_CHARS = 2_048;
|
|
23
|
+
export const ALPHA_SEARCH_TIMEOUT_MS = 35_000;
|
|
24
|
+
export const MAX_ALPHA_TIMEOUT_MS = 2 ** 32 - 1;
|
|
25
|
+
export const ALPHA_SEARCH_MAX_OUTPUT_TOKENS = 4_096;
|
|
26
|
+
|
|
27
|
+
const SEARCH_RESPONSE_LENGTHS = ["short", "medium", "long"] as const;
|
|
28
|
+
const FINANCE_ASSET_TYPES = ["equity", "fund", "crypto", "index"] as const;
|
|
29
|
+
const SPORTS_FUNCTIONS = ["schedule", "standings"] as const;
|
|
30
|
+
const SPORTS_LEAGUES = ["nba", "wnba", "nfl", "nhl", "mlb", "epl", "ncaamb", "ncaawb", "ipl"] as const;
|
|
31
|
+
const SPORTS_TOOL_NAMES = ["sports"] as const;
|
|
32
|
+
|
|
33
|
+
const SearchQueryParameters = Type.Object(
|
|
34
|
+
{
|
|
35
|
+
q: Type.String({ minLength: 1, maxLength: MAX_ALPHA_COMMAND_CHARS }),
|
|
36
|
+
recency: Type.Optional(
|
|
37
|
+
Type.Union([Type.Integer({ minimum: 0, maximum: MAX_ALPHA_RECENCY_DAYS }), Type.Null()]),
|
|
38
|
+
),
|
|
39
|
+
domains: Type.Optional(
|
|
40
|
+
Type.Union([
|
|
41
|
+
Type.Array(Type.String({ minLength: 1, maxLength: MAX_ALPHA_DOMAIN_CHARS }), {
|
|
42
|
+
maxItems: MAX_ALPHA_DOMAINS,
|
|
43
|
+
}),
|
|
44
|
+
Type.Null(),
|
|
45
|
+
]),
|
|
46
|
+
),
|
|
47
|
+
},
|
|
48
|
+
{ additionalProperties: false },
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const OpenParameters = Type.Object(
|
|
52
|
+
{
|
|
53
|
+
ref_id: Type.String({ minLength: 1, maxLength: MAX_ALPHA_REF_ID_CHARS }),
|
|
54
|
+
lineno: Type.Optional(
|
|
55
|
+
Type.Union([Type.Integer({ minimum: 1, maximum: MAX_ALPHA_LINE_NUMBER }), Type.Null()]),
|
|
56
|
+
),
|
|
57
|
+
},
|
|
58
|
+
{ additionalProperties: false },
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const ClickParameters = Type.Object(
|
|
62
|
+
{
|
|
63
|
+
ref_id: Type.String({ minLength: 1, maxLength: MAX_ALPHA_REF_ID_CHARS }),
|
|
64
|
+
id: Type.Integer({ minimum: 1, maximum: MAX_ALPHA_LINK_ID }),
|
|
65
|
+
},
|
|
66
|
+
{ additionalProperties: false },
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
const FindParameters = Type.Object(
|
|
70
|
+
{
|
|
71
|
+
ref_id: Type.String({ minLength: 1, maxLength: MAX_ALPHA_REF_ID_CHARS }),
|
|
72
|
+
pattern: Type.String({ minLength: 1, maxLength: MAX_ALPHA_COMMAND_CHARS }),
|
|
73
|
+
},
|
|
74
|
+
{ additionalProperties: false },
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
const ScreenshotParameters = Type.Object(
|
|
78
|
+
{
|
|
79
|
+
ref_id: Type.String({ minLength: 1, maxLength: MAX_ALPHA_REF_ID_CHARS }),
|
|
80
|
+
pageno: Type.Integer({ minimum: 0, maximum: MAX_ALPHA_PAGE_NUMBER }),
|
|
81
|
+
},
|
|
82
|
+
{ additionalProperties: false },
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
const FinanceParameters = Type.Object(
|
|
86
|
+
{
|
|
87
|
+
ticker: Type.String({ minLength: 1, maxLength: MAX_ALPHA_COMMAND_CHARS }),
|
|
88
|
+
type: StringEnum(FINANCE_ASSET_TYPES),
|
|
89
|
+
market: Type.Optional(
|
|
90
|
+
Type.Union([Type.String({ minLength: 1, maxLength: MAX_ALPHA_COMMAND_CHARS }), Type.Null()]),
|
|
91
|
+
),
|
|
92
|
+
},
|
|
93
|
+
{ additionalProperties: false },
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
const WeatherParameters = Type.Object(
|
|
97
|
+
{
|
|
98
|
+
location: Type.String({ minLength: 1, maxLength: MAX_ALPHA_COMMAND_CHARS }),
|
|
99
|
+
start: Type.Optional(
|
|
100
|
+
Type.Union([Type.String({ minLength: 1, maxLength: MAX_ALPHA_COMMAND_CHARS }), Type.Null()]),
|
|
101
|
+
),
|
|
102
|
+
duration: Type.Optional(
|
|
103
|
+
Type.Union([Type.Integer({ minimum: 1, maximum: MAX_ALPHA_WEATHER_DAYS }), Type.Null()]),
|
|
104
|
+
),
|
|
105
|
+
},
|
|
106
|
+
{ additionalProperties: false },
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
const SportsParameters = Type.Object(
|
|
110
|
+
{
|
|
111
|
+
tool: Type.Optional(Type.Union([StringEnum(SPORTS_TOOL_NAMES), Type.Null()])),
|
|
112
|
+
fn: StringEnum(SPORTS_FUNCTIONS),
|
|
113
|
+
league: StringEnum(SPORTS_LEAGUES),
|
|
114
|
+
team: Type.Optional(
|
|
115
|
+
Type.Union([Type.String({ minLength: 1, maxLength: MAX_ALPHA_COMMAND_CHARS }), Type.Null()]),
|
|
116
|
+
),
|
|
117
|
+
opponent: Type.Optional(
|
|
118
|
+
Type.Union([Type.String({ minLength: 1, maxLength: MAX_ALPHA_COMMAND_CHARS }), Type.Null()]),
|
|
119
|
+
),
|
|
120
|
+
date_from: Type.Optional(
|
|
121
|
+
Type.Union([Type.String({ minLength: 1, maxLength: MAX_ALPHA_COMMAND_CHARS }), Type.Null()]),
|
|
122
|
+
),
|
|
123
|
+
date_to: Type.Optional(
|
|
124
|
+
Type.Union([Type.String({ minLength: 1, maxLength: MAX_ALPHA_COMMAND_CHARS }), Type.Null()]),
|
|
125
|
+
),
|
|
126
|
+
num_games: Type.Optional(
|
|
127
|
+
Type.Union([Type.Integer({ minimum: 1, maximum: MAX_ALPHA_GAMES }), Type.Null()]),
|
|
128
|
+
),
|
|
129
|
+
locale: Type.Optional(
|
|
130
|
+
Type.Union([Type.String({ minLength: 1, maxLength: MAX_ALPHA_COMMAND_CHARS }), Type.Null()]),
|
|
131
|
+
),
|
|
132
|
+
},
|
|
133
|
+
{ additionalProperties: false },
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
const TimeParameters = Type.Object(
|
|
137
|
+
{
|
|
138
|
+
utc_offset: Type.String({ minLength: 1, maxLength: 32 }),
|
|
139
|
+
},
|
|
140
|
+
{ additionalProperties: false },
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
export const STANDALONE_WEB_RUN_PARAMETERS = Type.Object(
|
|
144
|
+
{
|
|
145
|
+
search_query: Type.Optional(Type.Union([Type.Array(SearchQueryParameters, { minItems: 1, maxItems: MAX_ALPHA_ACTIONS }), Type.Null()])),
|
|
146
|
+
image_query: Type.Optional(Type.Union([Type.Array(SearchQueryParameters, { minItems: 1, maxItems: MAX_ALPHA_ACTIONS }), Type.Null()])),
|
|
147
|
+
open: Type.Optional(Type.Union([Type.Array(OpenParameters, { minItems: 1, maxItems: MAX_ALPHA_ACTIONS }), Type.Null()])),
|
|
148
|
+
click: Type.Optional(Type.Union([Type.Array(ClickParameters, { minItems: 1, maxItems: MAX_ALPHA_ACTIONS }), Type.Null()])),
|
|
149
|
+
find: Type.Optional(Type.Union([Type.Array(FindParameters, { minItems: 1, maxItems: MAX_ALPHA_ACTIONS }), Type.Null()])),
|
|
150
|
+
screenshot: Type.Optional(Type.Union([Type.Array(ScreenshotParameters, { minItems: 1, maxItems: MAX_ALPHA_ACTIONS }), Type.Null()])),
|
|
151
|
+
finance: Type.Optional(Type.Union([Type.Array(FinanceParameters, { minItems: 1, maxItems: MAX_ALPHA_ACTIONS }), Type.Null()])),
|
|
152
|
+
weather: Type.Optional(Type.Union([Type.Array(WeatherParameters, { minItems: 1, maxItems: MAX_ALPHA_ACTIONS }), Type.Null()])),
|
|
153
|
+
sports: Type.Optional(Type.Union([Type.Array(SportsParameters, { minItems: 1, maxItems: MAX_ALPHA_ACTIONS }), Type.Null()])),
|
|
154
|
+
time: Type.Optional(Type.Union([Type.Array(TimeParameters, { minItems: 1, maxItems: MAX_ALPHA_ACTIONS }), Type.Null()])),
|
|
155
|
+
response_length: Type.Optional(Type.Union([StringEnum(SEARCH_RESPONSE_LENGTHS), Type.Null()])),
|
|
156
|
+
},
|
|
157
|
+
{ additionalProperties: false },
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
export type StandaloneWebRunParameters = Static<typeof STANDALONE_WEB_RUN_PARAMETERS>;
|
|
161
|
+
export type AlphaSearchResponseLength = (typeof SEARCH_RESPONSE_LENGTHS)[number];
|
|
162
|
+
export type FinanceAssetType = (typeof FINANCE_ASSET_TYPES)[number];
|
|
163
|
+
export type SportsFunction = (typeof SPORTS_FUNCTIONS)[number];
|
|
164
|
+
export type SportsLeague = (typeof SPORTS_LEAGUES)[number];
|
|
165
|
+
|
|
166
|
+
export type AlphaSearchQuery = {
|
|
167
|
+
q: string;
|
|
168
|
+
recency?: number;
|
|
169
|
+
domains?: string[];
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
export type AlphaOpenOperation = {
|
|
173
|
+
ref_id: string;
|
|
174
|
+
lineno?: number;
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
export type AlphaClickOperation = {
|
|
178
|
+
ref_id: string;
|
|
179
|
+
id: number;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
export type AlphaFindOperation = {
|
|
183
|
+
ref_id: string;
|
|
184
|
+
pattern: string;
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
export type AlphaScreenshotOperation = {
|
|
188
|
+
ref_id: string;
|
|
189
|
+
pageno: number;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
export type AlphaFinanceOperation = {
|
|
193
|
+
ticker: string;
|
|
194
|
+
type: FinanceAssetType;
|
|
195
|
+
market?: string;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
export type AlphaWeatherOperation = {
|
|
199
|
+
location: string;
|
|
200
|
+
start?: string;
|
|
201
|
+
duration?: number;
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
export type AlphaSportsOperation = {
|
|
205
|
+
tool?: "sports";
|
|
206
|
+
fn: SportsFunction;
|
|
207
|
+
league: SportsLeague;
|
|
208
|
+
team?: string;
|
|
209
|
+
opponent?: string;
|
|
210
|
+
date_from?: string;
|
|
211
|
+
date_to?: string;
|
|
212
|
+
num_games?: number;
|
|
213
|
+
locale?: string;
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
export type AlphaTimeOperation = {
|
|
217
|
+
utc_offset: string;
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
export type StandaloneWebRunCommands = {
|
|
221
|
+
search_query?: AlphaSearchQuery[];
|
|
222
|
+
image_query?: AlphaSearchQuery[];
|
|
223
|
+
open?: AlphaOpenOperation[];
|
|
224
|
+
click?: AlphaClickOperation[];
|
|
225
|
+
find?: AlphaFindOperation[];
|
|
226
|
+
screenshot?: AlphaScreenshotOperation[];
|
|
227
|
+
finance?: AlphaFinanceOperation[];
|
|
228
|
+
weather?: AlphaWeatherOperation[];
|
|
229
|
+
sports?: AlphaSportsOperation[];
|
|
230
|
+
time?: AlphaTimeOperation[];
|
|
231
|
+
response_length?: AlphaSearchResponseLength;
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
export type AlphaSearchRequest = {
|
|
235
|
+
id: string;
|
|
236
|
+
model: string;
|
|
237
|
+
commands: StandaloneWebRunCommands;
|
|
238
|
+
max_output_tokens: number;
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
export type AlphaSearchDetails = {
|
|
242
|
+
status: number;
|
|
243
|
+
responseId?: string;
|
|
244
|
+
encryptedOutput?: string;
|
|
245
|
+
results?: unknown[];
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
export type AlphaSearchClientFailureReason =
|
|
249
|
+
| "aborted"
|
|
250
|
+
| "timeout"
|
|
251
|
+
| "invalid-parameters"
|
|
252
|
+
| "invalid-url"
|
|
253
|
+
| "request-too-large"
|
|
254
|
+
| "authentication"
|
|
255
|
+
| "rate-limit"
|
|
256
|
+
| "request-rejected"
|
|
257
|
+
| "backend-unavailable"
|
|
258
|
+
| "network"
|
|
259
|
+
| "oversized-response"
|
|
260
|
+
| "malformed-response";
|
|
261
|
+
|
|
262
|
+
export type AlphaSearchClientResult =
|
|
263
|
+
| { ok: true; status: number; output: string; details: AlphaSearchDetails }
|
|
264
|
+
| {
|
|
265
|
+
ok: false;
|
|
266
|
+
reason: AlphaSearchClientFailureReason;
|
|
267
|
+
status?: number;
|
|
268
|
+
errorMessage: string;
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
export type AlphaSearchFetch = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
272
|
+
|
|
273
|
+
export class StandaloneWebRunError extends Error {
|
|
274
|
+
readonly code = "invalid-parameters" as const;
|
|
275
|
+
|
|
276
|
+
constructor(message: string) {
|
|
277
|
+
super(message);
|
|
278
|
+
this.name = "StandaloneWebRunError";
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
283
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function boundedText(value: string, maxChars: number): string {
|
|
287
|
+
return value.length <= maxChars ? value : `${value.slice(0, Math.max(0, maxChars - 1))}…`;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function invalid(field: string, message: string): never {
|
|
291
|
+
throw new StandaloneWebRunError(`${field}: ${boundedText(message, MAX_ALPHA_ERROR_CHARS)}.`);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function assertAllowedKeys(value: Record<string, unknown>, allowed: readonly string[], field: string): void {
|
|
295
|
+
const allowedSet = new Set(allowed);
|
|
296
|
+
for (const key of Object.keys(value)) {
|
|
297
|
+
if (!allowedSet.has(key)) invalid(field, `unexpected field "${boundedText(key, 128)}"`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function requiredString(value: unknown, field: string, maxChars: number): string {
|
|
302
|
+
if (typeof value !== "string") invalid(field, "expected a string");
|
|
303
|
+
const trimmed = value.trim();
|
|
304
|
+
if (!trimmed) invalid(field, "must not be blank");
|
|
305
|
+
if (trimmed.length > maxChars) invalid(field, `must be at most ${maxChars} characters`);
|
|
306
|
+
return trimmed;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function optionalString(value: unknown, field: string, maxChars: number): string | undefined {
|
|
310
|
+
if (value === undefined || value === null) return undefined;
|
|
311
|
+
if (typeof value !== "string") invalid(field, "expected a string or null");
|
|
312
|
+
const trimmed = value.trim();
|
|
313
|
+
if (!trimmed) return undefined;
|
|
314
|
+
if (trimmed.length > maxChars) invalid(field, `must be at most ${maxChars} characters`);
|
|
315
|
+
return trimmed;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function requiredInteger(value: unknown, field: string, min: number, max: number): number {
|
|
319
|
+
if (typeof value !== "number" || !Number.isInteger(value) || !Number.isFinite(value)) {
|
|
320
|
+
invalid(field, "expected an integer");
|
|
321
|
+
}
|
|
322
|
+
if (value < min || value > max) invalid(field, `must be between ${min} and ${max}`);
|
|
323
|
+
return value;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function optionalInteger(value: unknown, field: string, min: number, max: number): number | undefined {
|
|
327
|
+
if (value === undefined || value === null) return undefined;
|
|
328
|
+
return requiredInteger(value, field, min, max);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function optionalEnum<T extends string>(value: unknown, field: string, values: readonly T[]): T | undefined {
|
|
332
|
+
if (value === undefined || value === null) return undefined;
|
|
333
|
+
if (typeof value !== "string" || !values.includes(value as T)) {
|
|
334
|
+
invalid(field, `expected one of ${values.join(", ")}`);
|
|
335
|
+
}
|
|
336
|
+
return value as T;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function requiredEnum<T extends string>(value: unknown, field: string, values: readonly T[]): T {
|
|
340
|
+
const result = optionalEnum(value, field, values);
|
|
341
|
+
if (result === undefined) invalid(field, "is required");
|
|
342
|
+
return result;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function normalizeDomains(value: unknown, field: string): string[] | undefined {
|
|
346
|
+
if (value === undefined || value === null) return undefined;
|
|
347
|
+
if (!Array.isArray(value)) invalid(field, "expected an array or null");
|
|
348
|
+
if (value.length === 0) return undefined;
|
|
349
|
+
if (value.length > MAX_ALPHA_DOMAINS) invalid(field, `must contain at most ${MAX_ALPHA_DOMAINS} entries`);
|
|
350
|
+
const domains: string[] = [];
|
|
351
|
+
for (const [index, item] of value.entries()) {
|
|
352
|
+
const domain = requiredString(item, `${field}[${index}]`, MAX_ALPHA_DOMAIN_CHARS);
|
|
353
|
+
if (!domains.includes(domain)) domains.push(domain);
|
|
354
|
+
}
|
|
355
|
+
return domains;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function normalizeSearchQuery(value: unknown, field: string): AlphaSearchQuery {
|
|
359
|
+
if (!isRecord(value)) invalid(field, "expected an object");
|
|
360
|
+
assertAllowedKeys(value, ["q", "recency", "domains"], field);
|
|
361
|
+
const q = requiredString(value.q, `${field}.q`, MAX_ALPHA_COMMAND_CHARS);
|
|
362
|
+
const recency = optionalInteger(value.recency, `${field}.recency`, 0, MAX_ALPHA_RECENCY_DAYS);
|
|
363
|
+
const domains = normalizeDomains(value.domains, `${field}.domains`);
|
|
364
|
+
return {
|
|
365
|
+
q,
|
|
366
|
+
...(recency !== undefined ? { recency } : {}),
|
|
367
|
+
...(domains ? { domains } : {}),
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function normalizeOperationArray<T>(
|
|
372
|
+
value: unknown,
|
|
373
|
+
field: string,
|
|
374
|
+
normalizeItem: (item: unknown, itemField: string) => T,
|
|
375
|
+
): T[] | undefined {
|
|
376
|
+
if (value === undefined || value === null) return undefined;
|
|
377
|
+
if (!Array.isArray(value)) invalid(field, "expected an array or null");
|
|
378
|
+
if (value.length === 0) invalid(field, "must contain at least one operation");
|
|
379
|
+
if (value.length > MAX_ALPHA_ACTIONS) invalid(field, `must contain at most ${MAX_ALPHA_ACTIONS} operations`);
|
|
380
|
+
return value.map((item, index) => normalizeItem(item, `${field}[${index}]`));
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function normalizeOpen(value: unknown, field: string): AlphaOpenOperation {
|
|
384
|
+
if (!isRecord(value)) invalid(field, "expected an object");
|
|
385
|
+
assertAllowedKeys(value, ["ref_id", "lineno"], field);
|
|
386
|
+
const ref_id = requiredString(value.ref_id, `${field}.ref_id`, MAX_ALPHA_REF_ID_CHARS);
|
|
387
|
+
const lineno = optionalInteger(value.lineno, `${field}.lineno`, 1, MAX_ALPHA_LINE_NUMBER);
|
|
388
|
+
return { ref_id, ...(lineno !== undefined ? { lineno } : {}) };
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function normalizeClick(value: unknown, field: string): AlphaClickOperation {
|
|
392
|
+
if (!isRecord(value)) invalid(field, "expected an object");
|
|
393
|
+
assertAllowedKeys(value, ["ref_id", "id"], field);
|
|
394
|
+
return {
|
|
395
|
+
ref_id: requiredString(value.ref_id, `${field}.ref_id`, MAX_ALPHA_REF_ID_CHARS),
|
|
396
|
+
id: requiredInteger(value.id, `${field}.id`, 1, MAX_ALPHA_LINK_ID),
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
function normalizeFind(value: unknown, field: string): AlphaFindOperation {
|
|
401
|
+
if (!isRecord(value)) invalid(field, "expected an object");
|
|
402
|
+
assertAllowedKeys(value, ["ref_id", "pattern"], field);
|
|
403
|
+
return {
|
|
404
|
+
ref_id: requiredString(value.ref_id, `${field}.ref_id`, MAX_ALPHA_REF_ID_CHARS),
|
|
405
|
+
pattern: requiredString(value.pattern, `${field}.pattern`, MAX_ALPHA_COMMAND_CHARS),
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
function normalizeScreenshot(value: unknown, field: string): AlphaScreenshotOperation {
|
|
410
|
+
if (!isRecord(value)) invalid(field, "expected an object");
|
|
411
|
+
assertAllowedKeys(value, ["ref_id", "pageno"], field);
|
|
412
|
+
return {
|
|
413
|
+
ref_id: requiredString(value.ref_id, `${field}.ref_id`, MAX_ALPHA_REF_ID_CHARS),
|
|
414
|
+
pageno: requiredInteger(value.pageno, `${field}.pageno`, 0, MAX_ALPHA_PAGE_NUMBER),
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function normalizeFinance(value: unknown, field: string): AlphaFinanceOperation {
|
|
419
|
+
if (!isRecord(value)) invalid(field, "expected an object");
|
|
420
|
+
assertAllowedKeys(value, ["ticker", "type", "market"], field);
|
|
421
|
+
const market = optionalString(value.market, `${field}.market`, MAX_ALPHA_COMMAND_CHARS);
|
|
422
|
+
return {
|
|
423
|
+
ticker: requiredString(value.ticker, `${field}.ticker`, MAX_ALPHA_COMMAND_CHARS),
|
|
424
|
+
type: requiredEnum(value.type, `${field}.type`, FINANCE_ASSET_TYPES),
|
|
425
|
+
...(market !== undefined ? { market } : {}),
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
function normalizeWeather(value: unknown, field: string): AlphaWeatherOperation {
|
|
430
|
+
if (!isRecord(value)) invalid(field, "expected an object");
|
|
431
|
+
assertAllowedKeys(value, ["location", "start", "duration"], field);
|
|
432
|
+
const start = optionalString(value.start, `${field}.start`, MAX_ALPHA_COMMAND_CHARS);
|
|
433
|
+
const duration = optionalInteger(value.duration, `${field}.duration`, 1, MAX_ALPHA_WEATHER_DAYS);
|
|
434
|
+
return {
|
|
435
|
+
location: requiredString(value.location, `${field}.location`, MAX_ALPHA_COMMAND_CHARS),
|
|
436
|
+
...(start !== undefined ? { start } : {}),
|
|
437
|
+
...(duration !== undefined ? { duration } : {}),
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function normalizeSports(value: unknown, field: string): AlphaSportsOperation {
|
|
442
|
+
if (!isRecord(value)) invalid(field, "expected an object");
|
|
443
|
+
assertAllowedKeys(value, ["tool", "fn", "league", "team", "opponent", "date_from", "date_to", "num_games", "locale"], field);
|
|
444
|
+
const tool = optionalEnum(value.tool, `${field}.tool`, SPORTS_TOOL_NAMES);
|
|
445
|
+
const team = optionalString(value.team, `${field}.team`, MAX_ALPHA_COMMAND_CHARS);
|
|
446
|
+
const opponent = optionalString(value.opponent, `${field}.opponent`, MAX_ALPHA_COMMAND_CHARS);
|
|
447
|
+
const date_from = optionalString(value.date_from, `${field}.date_from`, MAX_ALPHA_COMMAND_CHARS);
|
|
448
|
+
const date_to = optionalString(value.date_to, `${field}.date_to`, MAX_ALPHA_COMMAND_CHARS);
|
|
449
|
+
const num_games = optionalInteger(value.num_games, `${field}.num_games`, 1, MAX_ALPHA_GAMES);
|
|
450
|
+
const locale = optionalString(value.locale, `${field}.locale`, MAX_ALPHA_COMMAND_CHARS);
|
|
451
|
+
return {
|
|
452
|
+
...(tool !== undefined ? { tool } : {}),
|
|
453
|
+
fn: requiredEnum(value.fn, `${field}.fn`, SPORTS_FUNCTIONS),
|
|
454
|
+
league: requiredEnum(value.league, `${field}.league`, SPORTS_LEAGUES),
|
|
455
|
+
...(team !== undefined ? { team } : {}),
|
|
456
|
+
...(opponent !== undefined ? { opponent } : {}),
|
|
457
|
+
...(date_from !== undefined ? { date_from } : {}),
|
|
458
|
+
...(date_to !== undefined ? { date_to } : {}),
|
|
459
|
+
...(num_games !== undefined ? { num_games } : {}),
|
|
460
|
+
...(locale !== undefined ? { locale } : {}),
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
function normalizeTime(value: unknown, field: string): AlphaTimeOperation {
|
|
465
|
+
if (!isRecord(value)) invalid(field, "expected an object");
|
|
466
|
+
assertAllowedKeys(value, ["utc_offset"], field);
|
|
467
|
+
return { utc_offset: requiredString(value.utc_offset, `${field}.utc_offset`, 32) };
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
export function normalizeStandaloneWebRunCommands(value: unknown): StandaloneWebRunCommands {
|
|
471
|
+
if (!isRecord(value)) invalid(WEB_RUN_TOOL_NAME, "expected an object");
|
|
472
|
+
assertAllowedKeys(value, [
|
|
473
|
+
"search_query",
|
|
474
|
+
"image_query",
|
|
475
|
+
"open",
|
|
476
|
+
"click",
|
|
477
|
+
"find",
|
|
478
|
+
"screenshot",
|
|
479
|
+
"finance",
|
|
480
|
+
"weather",
|
|
481
|
+
"sports",
|
|
482
|
+
"time",
|
|
483
|
+
"response_length",
|
|
484
|
+
], WEB_RUN_TOOL_NAME);
|
|
485
|
+
|
|
486
|
+
const search_query = normalizeOperationArray(value.search_query, "search_query", normalizeSearchQuery);
|
|
487
|
+
const image_query = normalizeOperationArray(value.image_query, "image_query", normalizeSearchQuery);
|
|
488
|
+
const open = normalizeOperationArray(value.open, "open", normalizeOpen);
|
|
489
|
+
const click = normalizeOperationArray(value.click, "click", normalizeClick);
|
|
490
|
+
const find = normalizeOperationArray(value.find, "find", normalizeFind);
|
|
491
|
+
const screenshot = normalizeOperationArray(value.screenshot, "screenshot", normalizeScreenshot);
|
|
492
|
+
const finance = normalizeOperationArray(value.finance, "finance", normalizeFinance);
|
|
493
|
+
const weather = normalizeOperationArray(value.weather, "weather", normalizeWeather);
|
|
494
|
+
const sports = normalizeOperationArray(value.sports, "sports", normalizeSports);
|
|
495
|
+
const time = normalizeOperationArray(value.time, "time", normalizeTime);
|
|
496
|
+
const response_length = optionalEnum(value.response_length, "response_length", SEARCH_RESPONSE_LENGTHS);
|
|
497
|
+
|
|
498
|
+
if (!search_query && !image_query && !open && !click && !find && !screenshot && !finance && !weather && !sports && !time) {
|
|
499
|
+
invalid(WEB_RUN_TOOL_NAME, "at least one search command is required");
|
|
500
|
+
}
|
|
501
|
+
return {
|
|
502
|
+
...(search_query ? { search_query } : {}),
|
|
503
|
+
...(image_query ? { image_query } : {}),
|
|
504
|
+
...(open ? { open } : {}),
|
|
505
|
+
...(click ? { click } : {}),
|
|
506
|
+
...(find ? { find } : {}),
|
|
507
|
+
...(screenshot ? { screenshot } : {}),
|
|
508
|
+
...(finance ? { finance } : {}),
|
|
509
|
+
...(weather ? { weather } : {}),
|
|
510
|
+
...(sports ? { sports } : {}),
|
|
511
|
+
...(time ? { time } : {}),
|
|
512
|
+
...(response_length !== undefined ? { response_length } : {}),
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
function utf8ByteLength(value: string): number {
|
|
517
|
+
return new TextEncoder().encode(value).byteLength;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
function freshRequestId(): string {
|
|
521
|
+
return globalThis.crypto.randomUUID();
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
export function buildAlphaSearchRequest(args: {
|
|
525
|
+
model: string;
|
|
526
|
+
commands: unknown;
|
|
527
|
+
id?: string;
|
|
528
|
+
maxOutputTokens?: number;
|
|
529
|
+
}): { request: AlphaSearchRequest; body: string } {
|
|
530
|
+
const model = requiredString(args.model, "model", MAX_ALPHA_COMMAND_CHARS);
|
|
531
|
+
const commands = normalizeStandaloneWebRunCommands(args.commands);
|
|
532
|
+
const id = requiredString(args.id ?? freshRequestId(), "id", MAX_ALPHA_REF_ID_CHARS);
|
|
533
|
+
const maxOutputTokens = args.maxOutputTokens ?? ALPHA_SEARCH_MAX_OUTPUT_TOKENS;
|
|
534
|
+
if (
|
|
535
|
+
typeof maxOutputTokens !== "number" ||
|
|
536
|
+
!Number.isInteger(maxOutputTokens) ||
|
|
537
|
+
!Number.isFinite(maxOutputTokens) ||
|
|
538
|
+
maxOutputTokens < 1 ||
|
|
539
|
+
maxOutputTokens > ALPHA_SEARCH_MAX_OUTPUT_TOKENS
|
|
540
|
+
) {
|
|
541
|
+
invalid("max_output_tokens", `must be an integer between 1 and ${ALPHA_SEARCH_MAX_OUTPUT_TOKENS}`);
|
|
542
|
+
}
|
|
543
|
+
const request: AlphaSearchRequest = {
|
|
544
|
+
id,
|
|
545
|
+
model,
|
|
546
|
+
commands,
|
|
547
|
+
max_output_tokens: maxOutputTokens,
|
|
548
|
+
};
|
|
549
|
+
const body = JSON.stringify(request);
|
|
550
|
+
if (utf8ByteLength(body) > MAX_ALPHA_REQUEST_BYTES) {
|
|
551
|
+
throw new StandaloneWebRunError(`${WEB_RUN_TOOL_NAME} request exceeds the 64 KiB limit.`);
|
|
552
|
+
}
|
|
553
|
+
return { request, body };
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
export function sanitizeAlphaDiagnostic(value: unknown, fallback: string): string {
|
|
557
|
+
const raw = typeof value === "string" ? value : value instanceof Error ? value.message : String(value ?? "");
|
|
558
|
+
const sanitized = raw
|
|
559
|
+
.replace(/Bearer\s+[^\s,;]+/gi, "Bearer [REDACTED]")
|
|
560
|
+
.replace(/((?:["'])(?:api[-_ ]?key|access[_-]?token|access[_-]?key|client[_-]?secret|token|secret|password|cookie|authorization)(?:["'])\s*:\s*["'])[^"']*(["'])/gi, "$1[REDACTED]$2")
|
|
561
|
+
.replace(/((?:api[-_ ]?key|access[_-]?token|access[_-]?key|client[_-]?secret|token|secret|password|cookie|authorization)\s*[:=]\s*)[^\s,;]+/gi, "$1[REDACTED]")
|
|
562
|
+
.replace(/([?&](?:api[-_ ]?key|access[_-]?token|access[_-]?key|client[_-]?secret|token|secret|password|cookie|authorization)=)[^&\s]+/gi, "$1[REDACTED]")
|
|
563
|
+
.trim();
|
|
564
|
+
return boundedText(sanitized || fallback, MAX_ALPHA_ERROR_CHARS);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
function providerErrorText(value: unknown): string | undefined {
|
|
568
|
+
if (!isRecord(value)) return undefined;
|
|
569
|
+
const candidate = isRecord(value.error) ? value.error : value;
|
|
570
|
+
const parts = [candidate.code, candidate.type, candidate.message].filter(
|
|
571
|
+
(item): item is string => typeof item === "string" && item.trim().length > 0,
|
|
572
|
+
);
|
|
573
|
+
return parts.length > 0 ? parts.join(" ") : undefined;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
function mapHttpFailure(status: number, payload: unknown): AlphaSearchClientFailureReason {
|
|
577
|
+
if (status === 401 || status === 403) return "authentication";
|
|
578
|
+
const providerText = providerErrorText(payload)?.toLowerCase() ?? "";
|
|
579
|
+
if (
|
|
580
|
+
status === 429 ||
|
|
581
|
+
/(?:rate|usage|billing)[-_ ]?limit|quota|insufficient[-_ ]?(?:quota|credit)/.test(providerText)
|
|
582
|
+
) {
|
|
583
|
+
return "rate-limit";
|
|
584
|
+
}
|
|
585
|
+
if (status >= 500) return "backend-unavailable";
|
|
586
|
+
return "request-rejected";
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
function defaultHttpMessage(status: number, reason: AlphaSearchClientFailureReason): string {
|
|
590
|
+
switch (reason) {
|
|
591
|
+
case "authentication":
|
|
592
|
+
return "Standalone Web Search authentication failed for the current model provider.";
|
|
593
|
+
case "rate-limit":
|
|
594
|
+
return "Standalone Web Search was rate-limited or the provider search quota was exhausted.";
|
|
595
|
+
case "backend-unavailable":
|
|
596
|
+
return "Standalone Web Search is temporarily unavailable at the configured gateway or upstream provider.";
|
|
597
|
+
default:
|
|
598
|
+
return `Standalone Web Search request was rejected (HTTP ${status}).`;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
async function readBoundedBody(
|
|
603
|
+
response: Response,
|
|
604
|
+
maxBytes: number,
|
|
605
|
+
): Promise<{ ok: true; bytes: Uint8Array } | { ok: false }> {
|
|
606
|
+
const contentLength = response.headers.get("content-length");
|
|
607
|
+
if (contentLength !== null) {
|
|
608
|
+
const parsed = Number(contentLength);
|
|
609
|
+
if (Number.isFinite(parsed) && parsed > maxBytes) return { ok: false };
|
|
610
|
+
}
|
|
611
|
+
if (!response.body) return { ok: true, bytes: new Uint8Array() };
|
|
612
|
+
|
|
613
|
+
const reader = response.body.getReader();
|
|
614
|
+
const chunks: Uint8Array[] = [];
|
|
615
|
+
let total = 0;
|
|
616
|
+
try {
|
|
617
|
+
while (true) {
|
|
618
|
+
const next = await reader.read();
|
|
619
|
+
if (next.done) break;
|
|
620
|
+
if (!next.value) continue;
|
|
621
|
+
total += next.value.byteLength;
|
|
622
|
+
if (total > maxBytes) {
|
|
623
|
+
await reader.cancel().catch(() => undefined);
|
|
624
|
+
return { ok: false };
|
|
625
|
+
}
|
|
626
|
+
chunks.push(next.value);
|
|
627
|
+
}
|
|
628
|
+
} finally {
|
|
629
|
+
reader.releaseLock();
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
const bytes = new Uint8Array(total);
|
|
633
|
+
let offset = 0;
|
|
634
|
+
for (const chunk of chunks) {
|
|
635
|
+
bytes.set(chunk, offset);
|
|
636
|
+
offset += chunk.byteLength;
|
|
637
|
+
}
|
|
638
|
+
return { ok: true, bytes };
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
function parseJson(bytes: Uint8Array): unknown {
|
|
642
|
+
return JSON.parse(new TextDecoder().decode(bytes)) as unknown;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
function parseAlphaSearchResponse(value: unknown, status: number):
|
|
646
|
+
| { ok: true; output: string; details: AlphaSearchDetails }
|
|
647
|
+
| { ok: false; reason: "malformed-response" | "oversized-response"; errorMessage: string } {
|
|
648
|
+
if (!isRecord(value)) {
|
|
649
|
+
return { ok: false, reason: "malformed-response", errorMessage: "Standalone Web Search returned a non-object response." };
|
|
650
|
+
}
|
|
651
|
+
if (typeof value.output !== "string" || !value.output.trim()) {
|
|
652
|
+
return { ok: false, reason: "malformed-response", errorMessage: "Standalone Web Search response did not contain usable output text." };
|
|
653
|
+
}
|
|
654
|
+
if (utf8ByteLength(value.output) > MAX_ALPHA_OUTPUT_BYTES) {
|
|
655
|
+
return { ok: false, reason: "oversized-response", errorMessage: "Standalone Web Search output exceeded the configured size limit." };
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
let encryptedOutput: string | undefined;
|
|
659
|
+
if (value.encrypted_output !== undefined) {
|
|
660
|
+
if (typeof value.encrypted_output !== "string") {
|
|
661
|
+
return { ok: false, reason: "malformed-response", errorMessage: "Standalone Web Search encrypted output was malformed." };
|
|
662
|
+
}
|
|
663
|
+
if (utf8ByteLength(value.encrypted_output) > MAX_ALPHA_OUTPUT_BYTES) {
|
|
664
|
+
return { ok: false, reason: "oversized-response", errorMessage: "Standalone Web Search encrypted output exceeded the configured size limit." };
|
|
665
|
+
}
|
|
666
|
+
encryptedOutput = value.encrypted_output;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
let results: unknown[] | undefined;
|
|
670
|
+
if (value.results !== undefined) {
|
|
671
|
+
if (!Array.isArray(value.results)) {
|
|
672
|
+
return { ok: false, reason: "malformed-response", errorMessage: "Standalone Web Search results were malformed." };
|
|
673
|
+
}
|
|
674
|
+
if (value.results.length > MAX_ALPHA_RESULTS) {
|
|
675
|
+
return { ok: false, reason: "oversized-response", errorMessage: "Standalone Web Search returned too many result entries." };
|
|
676
|
+
}
|
|
677
|
+
let serializedResults: string;
|
|
678
|
+
try {
|
|
679
|
+
const serialized = JSON.stringify(value.results);
|
|
680
|
+
if (typeof serialized !== "string") {
|
|
681
|
+
return { ok: false, reason: "malformed-response", errorMessage: "Standalone Web Search results could not be serialized." };
|
|
682
|
+
}
|
|
683
|
+
serializedResults = serialized;
|
|
684
|
+
results = structuredClone(value.results);
|
|
685
|
+
} catch {
|
|
686
|
+
return { ok: false, reason: "malformed-response", errorMessage: "Standalone Web Search results could not be serialized." };
|
|
687
|
+
}
|
|
688
|
+
if (utf8ByteLength(serializedResults) > MAX_ALPHA_RESULTS_BYTES) {
|
|
689
|
+
return { ok: false, reason: "oversized-response", errorMessage: "Standalone Web Search results exceeded the configured size limit." };
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
const responseId = typeof value.id === "string" && value.id.trim()
|
|
694
|
+
? boundedText(value.id.trim(), MAX_ALPHA_REF_ID_CHARS)
|
|
695
|
+
: undefined;
|
|
696
|
+
return {
|
|
697
|
+
ok: true,
|
|
698
|
+
output: value.output,
|
|
699
|
+
details: {
|
|
700
|
+
status,
|
|
701
|
+
...(responseId ? { responseId } : {}),
|
|
702
|
+
...(encryptedOutput !== undefined ? { encryptedOutput } : {}),
|
|
703
|
+
...(results !== undefined ? { results } : {}),
|
|
704
|
+
},
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
export async function requestAlphaSearch(args: {
|
|
709
|
+
runtime: ResponsesRuntime;
|
|
710
|
+
commands: StandaloneWebRunCommands;
|
|
711
|
+
signal?: AbortSignal;
|
|
712
|
+
fetchFn?: AlphaSearchFetch;
|
|
713
|
+
timeoutMs?: number;
|
|
714
|
+
requestId?: string;
|
|
715
|
+
}): Promise<AlphaSearchClientResult> {
|
|
716
|
+
if (args.signal?.aborted) {
|
|
717
|
+
return { ok: false, reason: "aborted", errorMessage: "Standalone Web Search was cancelled." };
|
|
718
|
+
}
|
|
719
|
+
const url = buildAlphaSearchUrl(args.runtime.baseUrl);
|
|
720
|
+
if (!url) {
|
|
721
|
+
return { ok: false, reason: "invalid-url", errorMessage: "Standalone Web Search has an invalid provider base URL." };
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
let request: { request: AlphaSearchRequest; body: string };
|
|
725
|
+
try {
|
|
726
|
+
request = buildAlphaSearchRequest({
|
|
727
|
+
model: args.runtime.model,
|
|
728
|
+
commands: args.commands,
|
|
729
|
+
id: args.requestId,
|
|
730
|
+
});
|
|
731
|
+
} catch (error) {
|
|
732
|
+
const errorMessage = sanitizeAlphaDiagnostic(error, "Standalone Web Search request was invalid.");
|
|
733
|
+
return {
|
|
734
|
+
ok: false,
|
|
735
|
+
reason: errorMessage.includes("exceeds the 64 KiB limit") ? "request-too-large" : "invalid-parameters",
|
|
736
|
+
errorMessage,
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
const fetchFn = args.fetchFn ?? globalThis.fetch;
|
|
741
|
+
const timeoutMs = args.timeoutMs ?? ALPHA_SEARCH_TIMEOUT_MS;
|
|
742
|
+
if (!Number.isInteger(timeoutMs) || !Number.isFinite(timeoutMs) || timeoutMs < 0 || timeoutMs > MAX_ALPHA_TIMEOUT_MS) {
|
|
743
|
+
return {
|
|
744
|
+
ok: false,
|
|
745
|
+
reason: "invalid-parameters",
|
|
746
|
+
errorMessage: "Standalone Web Search timeout must be a non-negative bounded integer.",
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
const timeoutSignal = AbortSignal.timeout(timeoutMs);
|
|
750
|
+
// Bun implements AbortSignal.any() with weak references to its inputs; keep
|
|
751
|
+
// the timeout signal live for the duration of this request so a short test
|
|
752
|
+
// or a real fast timeout cannot be lost before it fires.
|
|
753
|
+
timeoutSignal.addEventListener("abort", () => undefined, { once: true });
|
|
754
|
+
const signal = args.signal ? AbortSignal.any([args.signal, timeoutSignal]) : timeoutSignal;
|
|
755
|
+
if (signal.aborted) {
|
|
756
|
+
return timeoutSignal.aborted && !args.signal?.aborted
|
|
757
|
+
? { ok: false, reason: "timeout", errorMessage: "Standalone Web Search timed out. The request was not retried automatically." }
|
|
758
|
+
: { ok: false, reason: "aborted", errorMessage: "Standalone Web Search was cancelled." };
|
|
759
|
+
}
|
|
760
|
+
let response: Response;
|
|
761
|
+
try {
|
|
762
|
+
response = await fetchFn(url, {
|
|
763
|
+
method: "POST",
|
|
764
|
+
redirect: "error",
|
|
765
|
+
headers: buildResponsesRequestHeaders(args.runtime, {
|
|
766
|
+
accept: "application/json",
|
|
767
|
+
sessionId: args.runtime.sessionId,
|
|
768
|
+
}),
|
|
769
|
+
body: request.body,
|
|
770
|
+
signal,
|
|
771
|
+
});
|
|
772
|
+
} catch (error) {
|
|
773
|
+
if (args.signal?.aborted) {
|
|
774
|
+
return { ok: false, reason: "aborted", errorMessage: "Standalone Web Search was cancelled." };
|
|
775
|
+
}
|
|
776
|
+
if (timeoutSignal.aborted) {
|
|
777
|
+
return {
|
|
778
|
+
ok: false,
|
|
779
|
+
reason: "timeout",
|
|
780
|
+
errorMessage: "Standalone Web Search timed out. The request was not retried automatically.",
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
return {
|
|
784
|
+
ok: false,
|
|
785
|
+
reason: "network",
|
|
786
|
+
errorMessage: sanitizeAlphaDiagnostic(
|
|
787
|
+
error,
|
|
788
|
+
"Standalone Web Search network request failed. The request was not retried automatically.",
|
|
789
|
+
),
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
let bounded: Awaited<ReturnType<typeof readBoundedBody>>;
|
|
794
|
+
try {
|
|
795
|
+
bounded = await readBoundedBody(response, MAX_ALPHA_RESPONSE_BYTES);
|
|
796
|
+
} catch (error) {
|
|
797
|
+
if (args.signal?.aborted) {
|
|
798
|
+
return { ok: false, reason: "aborted", status: response.status, errorMessage: "Standalone Web Search was cancelled." };
|
|
799
|
+
}
|
|
800
|
+
if (timeoutSignal.aborted) {
|
|
801
|
+
return {
|
|
802
|
+
ok: false,
|
|
803
|
+
reason: "timeout",
|
|
804
|
+
status: response.status,
|
|
805
|
+
errorMessage: "Standalone Web Search timed out while reading the response. The request was not retried automatically.",
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
return {
|
|
809
|
+
ok: false,
|
|
810
|
+
reason: "network",
|
|
811
|
+
status: response.status,
|
|
812
|
+
errorMessage: sanitizeAlphaDiagnostic(
|
|
813
|
+
error,
|
|
814
|
+
"Standalone Web Search response could not be read. The request was not retried automatically.",
|
|
815
|
+
),
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
if (args.signal?.aborted) {
|
|
819
|
+
return { ok: false, reason: "aborted", status: response.status, errorMessage: "Standalone Web Search was cancelled." };
|
|
820
|
+
}
|
|
821
|
+
if (timeoutSignal.aborted) {
|
|
822
|
+
return {
|
|
823
|
+
ok: false,
|
|
824
|
+
reason: "timeout",
|
|
825
|
+
status: response.status,
|
|
826
|
+
errorMessage: "Standalone Web Search timed out while reading the response. The request was not retried automatically.",
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
if (!bounded.ok) {
|
|
830
|
+
return {
|
|
831
|
+
ok: false,
|
|
832
|
+
reason: "oversized-response",
|
|
833
|
+
status: response.status,
|
|
834
|
+
errorMessage: "Standalone Web Search response exceeded the configured size limit.",
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
let payload: unknown;
|
|
839
|
+
try {
|
|
840
|
+
payload = parseJson(bounded.bytes);
|
|
841
|
+
} catch {
|
|
842
|
+
const reason = response.ok ? "malformed-response" : mapHttpFailure(response.status, undefined);
|
|
843
|
+
return {
|
|
844
|
+
ok: false,
|
|
845
|
+
reason,
|
|
846
|
+
status: response.status,
|
|
847
|
+
errorMessage: response.ok
|
|
848
|
+
? "Standalone Web Search returned invalid JSON."
|
|
849
|
+
: defaultHttpMessage(response.status, reason),
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
if (!response.ok) {
|
|
854
|
+
const reason = mapHttpFailure(response.status, payload);
|
|
855
|
+
return {
|
|
856
|
+
ok: false,
|
|
857
|
+
reason,
|
|
858
|
+
status: response.status,
|
|
859
|
+
errorMessage: sanitizeAlphaDiagnostic(
|
|
860
|
+
providerErrorText(payload),
|
|
861
|
+
defaultHttpMessage(response.status, reason),
|
|
862
|
+
),
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
const parsed = parseAlphaSearchResponse(payload, response.status);
|
|
867
|
+
if (!parsed.ok) return { ...parsed, status: response.status };
|
|
868
|
+
return { ok: true, status: response.status, output: parsed.output, details: parsed.details };
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
export const _alphaClientTest = {
|
|
872
|
+
readBoundedBody,
|
|
873
|
+
parseAlphaSearchResponse,
|
|
874
|
+
sanitizeAlphaDiagnostic,
|
|
875
|
+
utf8ByteLength,
|
|
876
|
+
};
|