@danceiny/gotry 0.0.1-rc.18 → 0.0.1-rc.19

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 (137) hide show
  1. package/README.md +42 -16
  2. package/README.zh-CN.md +37 -15
  3. package/bin/gotry-bootstrap.js +236 -3
  4. package/bin/gotry-inner.js +66 -20
  5. package/bin/gotry-runtime-resolution.d.ts +1 -1
  6. package/bin/gotry-runtime-resolution.js +7 -8
  7. package/cordis.gotry-patch.yml +15 -5
  8. package/data/stations-12306-verify.json +524 -0
  9. package/dist/capabilities/agent-reach.js +4 -4
  10. package/dist/capabilities/channel-health.js +103 -0
  11. package/dist/capabilities/channel-registry.js +213 -0
  12. package/dist/capabilities/doctor.js +285 -0
  13. package/dist/capabilities/effect.js +178 -5
  14. package/dist/capabilities/flyai.js +13 -0
  15. package/dist/capabilities/session/adapters/ctrip-hotel.js +207 -0
  16. package/dist/capabilities/session/adapters/rail-12306.js +285 -0
  17. package/dist/capabilities/session/extension-bridge.js +14 -1
  18. package/dist/capabilities/session/extension-channel.js +4 -2
  19. package/dist/capabilities/session/extension-distribution.js +1 -1
  20. package/dist/capabilities/session-search.js +311 -0
  21. package/dist/capabilities/visa-policy.js +126 -0
  22. package/dist/scripts/agent-planning-turn-deadline-e2e.js +304 -0
  23. package/dist/scripts/agent-planning-turn-deadline-tests.js +281 -0
  24. package/dist/scripts/benchmark-environment-bridge-e2e.js +5 -10
  25. package/dist/scripts/benchmark-environment-bridge-tests.js +148 -142
  26. package/dist/scripts/booking-copilot-availability-ledger-binding-tests.js +26 -26
  27. package/dist/scripts/{booking-copilot-availability-policy-v2-tests.js → booking-copilot-availability-policy-tests.js} +115 -115
  28. package/dist/scripts/booking-copilot-crossrepo-fixture-server.js +41 -1
  29. package/dist/scripts/booking-copilot-dsh-core-proof-tests.js +75 -120
  30. package/dist/scripts/booking-copilot-dsh-planner-proof-tests.js +370 -61
  31. package/dist/scripts/booking-copilot-dsh-plugin-proof-tests.js +2 -2
  32. package/dist/scripts/booking-copilot-event-sequence-concurrency-proof-tests.js +7 -3
  33. package/dist/scripts/booking-copilot-gap-code-contract-proof-tests.js +15 -9
  34. package/dist/scripts/booking-copilot-operation-ledger-concurrency-proof-tests.js +19 -11
  35. package/dist/scripts/booking-copilot-receipt-ledger-concurrency-proof-tests.js +16 -52
  36. package/dist/scripts/booking-copilot-runtime-proof-tests.js +3953 -155
  37. package/dist/scripts/booking-copilot-server-proof-tests.js +58 -23
  38. package/dist/scripts/booking-copilot-startup-proof-tests.js +10 -119
  39. package/dist/scripts/booking-surface-contract-proof-tests.js +1154 -326
  40. package/dist/scripts/bootstrap-tests.js +87 -2
  41. package/dist/scripts/build-metrics-report.js +339 -0
  42. package/dist/scripts/channel-probe-tests.js +148 -0
  43. package/dist/scripts/channel-probe.js +252 -0
  44. package/dist/scripts/channel-registry-tests.js +262 -0
  45. package/dist/scripts/doctor-tests.js +121 -0
  46. package/dist/scripts/effect-tests.js +274 -1
  47. package/dist/scripts/extension-tests.js +129 -11
  48. package/dist/scripts/fact-gate-tests.js +91 -2
  49. package/dist/scripts/flyai-tests.js +17 -1
  50. package/dist/scripts/hbcli-e2e-tests.js +1 -3
  51. package/dist/scripts/metrics-report-tests.js +288 -0
  52. package/dist/scripts/persona-surface-guard-tests.js +19 -0
  53. package/dist/scripts/session-tests.js +401 -1
  54. package/dist/scripts/smoke.js +100 -83
  55. package/dist/scripts/turn-handoff-collect-tests.js +216 -0
  56. package/dist/scripts/turn-handoff-collect.js +189 -0
  57. package/dist/scripts/turn-policy-tests.js +56 -0
  58. package/dist/scripts/typed-contract-canary.js +261 -0
  59. package/dist/scripts/visa-policy-tests.js +75 -0
  60. package/dist/scripts/wish-channel-gate-tests.js +111 -0
  61. package/dist/src/artifact-gate.js +91 -3
  62. package/dist/src/benchmark-agent-conformance.js +7 -4
  63. package/dist/src/benchmark-environment-bridge.js +68 -7
  64. package/dist/src/bookable-facts.js +62 -3
  65. package/dist/src/booking-surface/{availability-policy-v2.js → availability-policy.js} +89 -89
  66. package/dist/src/booking-surface/canonical-schema.js +8 -22
  67. package/dist/src/booking-surface/contracts.js +70 -19
  68. package/dist/src/booking-surface/dsh-planner.js +310 -177
  69. package/dist/src/booking-surface/dsh-plugin.js +3 -3
  70. package/dist/src/booking-surface/index.js +1 -5
  71. package/dist/src/booking-surface/profile.js +1 -1
  72. package/dist/src/booking-surface/runtime.js +1682 -247
  73. package/dist/src/booking-surface/server.js +371 -185
  74. package/dist/src/booking-surface/startup.js +17 -27
  75. package/dist/src/booking-surface/validation.js +270 -760
  76. package/dist/src/index.js +735 -149
  77. package/dist/src/turn-deadline.js +292 -0
  78. package/dist/src/turn-policy.js +146 -0
  79. package/dist/src/wish-pool.js +5 -0
  80. package/extension/background.js +23 -4
  81. package/extension/content-main.js +47 -9
  82. package/extension/manifest.json +27 -9
  83. package/package.json +6 -26
  84. package/schemas/booking.surface.schema.json +2593 -0
  85. package/ts/capabilities/agent-reach.ts +4 -4
  86. package/ts/capabilities/flyai.ts +21 -3
  87. package/ts/capabilities/session/action-cache.ts +1 -1
  88. package/ts/capabilities/session/adapters/ctrip-hotel.ts +238 -0
  89. package/ts/capabilities/session/adapters/rail-12306.ts +293 -0
  90. package/ts/capabilities/session/extension-bridge.ts +32 -2
  91. package/ts/capabilities/session/extension-channel.ts +9 -8
  92. package/ts/capabilities/session/extension-distribution.ts +3 -1
  93. package/ts/capabilities/session/health-watch.ts +1 -1
  94. package/ts/capabilities/session/read-guard.ts +1 -1
  95. package/ts/capabilities/session/wizard.ts +1 -1
  96. package/ts/capabilities/session-search.ts +323 -1
  97. package/ts/package.json +1 -0
  98. package/ts/scripts/turn-handoff-collect.ts +178 -0
  99. package/ts/src/artifact-gate.ts +82 -2
  100. package/ts/src/benchmark-agent-conformance.ts +14 -6
  101. package/ts/src/benchmark-environment-bridge.ts +29 -10
  102. package/ts/src/bookable-facts.ts +109 -5
  103. package/ts/src/booking-saga.ts +1 -1
  104. package/ts/src/booking-surface/{availability-policy-v2.ts → availability-policy.ts} +124 -125
  105. package/ts/src/booking-surface/canonical-schema.js +8 -22
  106. package/ts/src/booking-surface/contracts.ts +278 -239
  107. package/ts/src/booking-surface/dsh-planner.ts +333 -194
  108. package/ts/src/booking-surface/dsh-plugin.js +3 -3
  109. package/ts/src/booking-surface/index.ts +1 -5
  110. package/ts/src/booking-surface/profile.ts +11 -11
  111. package/ts/src/booking-surface/runtime.ts +1351 -351
  112. package/ts/src/booking-surface/server.ts +282 -175
  113. package/ts/src/booking-surface/startup.ts +36 -48
  114. package/ts/src/booking-surface/validation.ts +194 -442
  115. package/ts/src/contracts.ts +1 -1
  116. package/ts/src/index.ts +489 -171
  117. package/ts/src/loop.ts +1 -1
  118. package/ts/src/state-ledger.ts +1 -1
  119. package/ts/src/turn-deadline.ts +361 -0
  120. package/ts/src/turn-policy.ts +154 -0
  121. package/ts/src/wish-pool.ts +17 -4
  122. package/dist/scripts/agent-planning-budget-e2e.js +0 -227
  123. package/dist/scripts/agent-planning-budget-tests.js +0 -173
  124. package/dist/scripts/booking-copilot-v2-runtime-proof-tests.js +0 -3935
  125. package/dist/scripts/booking-surface-v2-contract-proof-tests.js +0 -1174
  126. package/dist/src/booking-surface/contracts-v2.js +0 -89
  127. package/dist/src/booking-surface/runtime-v2.js +0 -1771
  128. package/dist/src/booking-surface/server-v2.js +0 -334
  129. package/dist/src/booking-surface/validation-v2.js +0 -319
  130. package/dist/src/tool-budget.js +0 -136
  131. package/schemas/booking.surface.v1.schema.json +0 -927
  132. package/schemas/booking.surface.v2.schema.json +0 -61
  133. package/ts/src/booking-surface/contracts-v2.ts +0 -118
  134. package/ts/src/booking-surface/runtime-v2.ts +0 -1466
  135. package/ts/src/booking-surface/server-v2.ts +0 -247
  136. package/ts/src/booking-surface/validation-v2.ts +0 -205
  137. package/ts/src/tool-budget.ts +0 -165
@@ -5,9 +5,9 @@
5
5
  * is limited to a user turn or an explanation and is never parsed as an action.
6
6
  */
7
7
 
8
- export const BOOKING_SURFACE_SCHEMA_VERSION = 'booking.surface.v1' as const
9
- /** SHA-256 of schemas/booking.surface.v1.schema.json; package proof pins drift. */
10
- export const BOOKING_SURFACE_SCHEMA_SHA256 = 'd9c2194ec839bd1168e70e8a201581addc005039d9b299660e20650bbb65df81' as const
8
+ export const BOOKING_SURFACE_SCHEMA_VERSION = 'booking.surface' as const
9
+ /** SHA-256 of schemas/booking.surface.schema.json; package proof pins drift. */
10
+ export const BOOKING_SURFACE_SCHEMA_SHA256 = 'f9a73339c4c51280bfd63ba67c8b9f495fbbb796573b7a24d35de572f17f5127' as const
11
11
  export const BOOKING_SURFACE_VERSION_HEADER = 'x-booking-surface-version' as const
12
12
  export const BOOKING_SURFACE_SCHEMA_SHA256_HEADER = 'x-booking-surface-schema-sha256' as const
13
13
 
@@ -17,364 +17,403 @@ export const BOOKING_SURFACES = [
17
17
  'storefront',
18
18
  'payment_link',
19
19
  ] as const
20
- export type BookingSurfaceV1 = (typeof BOOKING_SURFACES)[number]
21
-
22
- export const BOOKING_READ_ACTION_KINDS = [
23
- 'search.patch',
24
- 'search.run',
25
- 'results.view.patch',
26
- 'hotel.focus',
27
- 'hotel.select',
28
- 'offers.query',
29
- 'offers.view.patch',
30
- 'offers.compare',
31
- 'offer.select',
32
- 'offer.check',
33
- 'checkout.prepare',
34
- 'order.observe',
35
- ] as const
36
- export type BookingReadActionKindV1 = (typeof BOOKING_READ_ACTION_KINDS)[number]
37
-
38
- export const BOOKING_RECEIPT_STATUSES = [
39
- 'applied',
40
- 'needs_input',
41
- 'partial',
42
- 'no_match',
43
- 'unavailable',
44
- 'changed',
45
- 'stale',
46
- 'unsupported',
47
- 'failed',
48
- ] as const
49
- export type ActionReceiptStatusV1 = (typeof BOOKING_RECEIPT_STATUSES)[number]
50
-
51
- export const BOOKING_SURFACE_EVENT_KINDS = [
52
- 'status',
53
- 'question',
54
- 'operation',
55
- 'explanation',
56
- 'terminal',
57
- 'error',
58
- ] as const
59
- export type BookingSurfaceEventKindV1 = (typeof BOOKING_SURFACE_EVENT_KINDS)[number]
60
-
61
- export type ContextRefV1 = string
62
- export type FactRefV1 = string
63
- export type HotelRefV1 = string
64
- export type OfferRefV1 = string
65
- export type VerifiedOfferRefV1 = string
66
- export type OrderRefV1 = string
67
-
68
- export type CriterionStrengthV1 = 'must' | 'prefer'
69
- export interface CriterionV1<T> {
70
- strength: CriterionStrengthV1
20
+ export type BookingSurface = (typeof BOOKING_SURFACES)[number]
21
+
22
+ /**
23
+ * Process composition modes are deliberately separate from the payload
24
+ * schema. The default accepts turns already bound by HotelByte's BFF; the
25
+ * second mode is reserved for an in-process BFF binding seam.
26
+ */
27
+ export const BOOKING_COPILOT_INGRESS_MODES = ['bff-bound-turn-only', 'bff-ingress-binding'] as const
28
+ export type BookingCopilotIngressMode = typeof BOOKING_COPILOT_INGRESS_MODES[number]
29
+ export const BOOKING_COPILOT_ACCEPTED_TURN_KINDS = ['user.turn', 'action.receipt.continuation'] as const
30
+ export const BOOKING_COPILOT_INGRESS_TURN_KIND = 'user.turn.ingress' as const
31
+ /** Hard task-level operation budget. The counter is persisted in the ledger. */
32
+ export const BOOKING_COPILOT_MAX_OPERATIONS = 20 as const
33
+
34
+ export const BOOKING_READ_ACTION_KINDS = ['search.patch','search.run','results.view.patch','hotel.focus','hotel.select','offers.query','offers.view.patch','offers.compare','offer.select','offer.check','checkout.prepare','order.observe'] as const
35
+ export type BookingReadActionKind = typeof BOOKING_READ_ACTION_KINDS[number]
36
+ /** Product-owned least-privilege action matrix. BFF bindings may narrow these lists, never expand them. */
37
+ export const BOOKING_SURFACE_ALLOWED_ACTIONS: Record<BookingSurface, readonly BookingReadActionKind[]> = {
38
+ tenant: BOOKING_READ_ACTION_KINDS,
39
+ customer_portal: BOOKING_READ_ACTION_KINDS,
40
+ storefront: ['search.patch', 'search.run', 'results.view.patch', 'hotel.focus'],
41
+ payment_link: ['search.patch', 'search.run', 'results.view.patch', 'hotel.focus', 'hotel.select'],
42
+ }
43
+ /** Stable product-matrix observation for UAT and server readiness proofs. */
44
+ export function bookingSurfaceAllowedActions(surface: BookingSurface): BookingReadActionKind[] {
45
+ return [...BOOKING_SURFACE_ALLOWED_ACTIONS[surface]]
46
+ }
47
+
48
+ export type BookingRequestKey = string
49
+ /** Runtime-owned idempotency key; this is not a browser request key. */
50
+ export type BookingInternalDecisionKey = string
51
+
52
+ export const BOOKING_BLOCKER_CODES = ['no_hotels_matched','hotel_not_visible','hotel_rates_failed','criterion_must_not_met','offer_target_not_reached','offer_unavailable'] as const
53
+ export type BookingBlockerCode = typeof BOOKING_BLOCKER_CODES[number]
54
+ export const BOOKING_GAP_CODES = ['byos_mapped_risk','check_avail_failed','check_avail_unverified','component_executor_unavailable','hotel_not_visible','hotel_rates_failed','offer_facts_changed','offer_not_loaded','offer_unavailable','order_not_found','order_outcome_not_observed','order_state_unknown','order_status_unavailable','requested_offers_not_loaded','search_failed','search_form_invalid','search_session_expired','search_terminal_timeout','stale_revision','surface_adapter_failed','undo_token_not_found','unhandled','unsupported','verified_offer_required','workspace_changed_during_action','criterion_must_not_met','no_hotels_matched','offer_target_not_reached'] as const
55
+ export type BookingGapCode = typeof BOOKING_GAP_CODES[number]
56
+ export type BookingBlockerScope = 'search' | 'offer' | 'availability' | 'checkout'
57
+
58
+ export type CriterionStrength = 'must' | 'prefer'
59
+ export interface Criterion<T> {
60
+ strength: CriterionStrength
71
61
  value: T
72
62
  }
73
63
 
74
- export interface MoneyV1 {
64
+ export interface Money {
75
65
  /** Decimal string supplied by the authoritative page object; never recomputed by GoTry. */
76
66
  amount: string
77
67
  currency: string
78
- sourceFactRef: FactRefV1
68
+ sourceFactRef: string
79
69
  }
80
70
 
81
- export interface OccupancyRoomV1 {
71
+ export interface OccupancyRoom {
82
72
  adults: number
83
73
  childAges: number[]
84
74
  }
85
75
 
86
- export interface SearchCriteriaPatchV1 {
76
+ export interface SearchCriteriaPatch {
87
77
  destination?: {
88
78
  query?: string
89
79
  placeRef?: string
90
80
  }
91
- hotel?: CriterionV1<{
81
+ hotel?: Criterion<{
92
82
  name?: string
93
- hotelRef?: HotelRefV1
83
+ hotelRef?: string
94
84
  }>
95
85
  stay?: {
96
86
  checkIn?: string
97
87
  checkOut?: string
98
88
  }
99
89
  occupancy?: {
100
- rooms: OccupancyRoomV1[]
90
+ rooms: OccupancyRoom[]
101
91
  }
102
- budget?: CriterionV1<{
103
- min?: MoneyV1
104
- max?: MoneyV1
92
+ budget?: Criterion<{
93
+ min?: Money
94
+ max?: Money
105
95
  }>
106
- starRating?: CriterionV1<{
96
+ starRating?: Criterion<{
107
97
  min?: number
108
98
  max?: number
109
99
  }>
110
- guestRating?: CriterionV1<{
100
+ guestRating?: Criterion<{
111
101
  min: number
112
102
  }>
113
- facilities?: CriterionV1<{
103
+ facilities?: Criterion<{
114
104
  allOf: string[]
115
105
  }>
116
- distance?: CriterionV1<{
106
+ distance?: Criterion<{
117
107
  anchorLabel?: string
118
108
  anchorRef?: string
119
109
  maxKm: number
120
110
  }>
121
111
  }
122
112
 
123
- export type ResultSortV1 =
113
+ export type ResultSort =
124
114
  | 'recommended'
125
115
  | 'price_asc'
126
116
  | 'price_desc'
127
117
  | 'rating_desc'
128
118
  | 'distance_asc'
129
119
 
130
- export interface ResultsViewPatchV1 {
120
+ export interface ResultsViewPatch {
131
121
  starRating?: { min?: number; max?: number } | null
132
122
  guestRatingMin?: number | null
133
123
  facilitiesAllOf?: string[] | null
134
124
  distance?: { anchorRef: string; maxKm: number } | null
135
- price?: { min?: MoneyV1; max?: MoneyV1 } | null
136
- sort?: ResultSortV1
125
+ price?: { min?: Money; max?: Money } | null
126
+ sort?: ResultSort
137
127
  }
138
128
 
139
- export interface OfferCriteriaV1 {
140
- roomType?: CriterionV1<string[]>
141
- bedType?: CriterionV1<string[]>
142
- meals?: CriterionV1<string[]>
143
- freeCancellation?: CriterionV1<boolean>
144
- freeCancellationUntil?: CriterionV1<string>
145
- totalPriceMax?: CriterionV1<MoneyV1>
146
- roomsAvailableMin?: CriterionV1<number>
147
- payAtProperty?: CriterionV1<boolean>
148
- mobileRate?: CriterionV1<boolean>
129
+ export interface OfferCriteria {
130
+ roomType?: Criterion<string[]>
131
+ bedType?: Criterion<string[]>
132
+ meals?: Criterion<string[]>
133
+ freeCancellation?: Criterion<boolean>
134
+ freeCancellationUntil?: Criterion<string>
135
+ totalPriceMax?: Criterion<Money>
136
+ roomsAvailableMin?: Criterion<number>
137
+ payAtProperty?: Criterion<boolean>
138
+ mobileRate?: Criterion<boolean>
149
139
  targetCount?: number
150
140
  sort?: 'best_match' | 'total_price_asc' | 'cancellation_latest'
151
141
  }
152
142
 
153
- export type EvidenceLevelV1 = 'listed' | 'rate_loaded' | 'checked'
154
-
155
- export interface SurfaceCapabilitiesV1 {
156
- surface: BookingSurfaceV1
157
- allowedActions: BookingReadActionKindV1[]
158
- }
143
+ export type EvidenceLevel = 'listed' | 'rate_loaded' | 'checked'
159
144
 
160
- export interface SearchDraftSnapshotV1 {
145
+ export interface SearchDraftSnapshot {
161
146
  destination?: { query?: string; placeRef?: string }
162
147
  stay?: { checkIn?: string; checkOut?: string }
163
- occupancy?: { rooms: OccupancyRoomV1[] }
164
- criteria?: SearchCriteriaPatchV1
148
+ occupancy?: { rooms: OccupancyRoom[] }
149
+ criteria?: SearchCriteriaPatch
165
150
  }
166
151
 
167
- export interface ResultViewSnapshotV1 {
152
+ export interface ResultViewSnapshot {
168
153
  status: 'idle' | 'loading' | 'ready' | 'partial' | 'failed'
169
- filters?: ResultsViewPatchV1
170
- sort?: ResultSortV1
154
+ filters?: ResultsViewPatch
155
+ sort?: ResultSort
171
156
  resultCount?: number
172
157
  searchSessionRef?: string
173
158
  }
174
159
 
175
- export interface VisibleHotelFactV1 {
176
- hotelRef: HotelRefV1
160
+ export interface VisibleHotelFact {
161
+ hotelRef: string
177
162
  name: string
178
163
  starRating?: number
179
164
  guestRating?: number
180
165
  distanceKm?: number
181
166
  facilityCodes?: string[]
182
- factRefs: FactRefV1[]
167
+ factRefs: string[]
183
168
  }
184
169
 
185
- export interface LoadedOfferFactV1 {
186
- offerRef: OfferRefV1
187
- hotelRef: HotelRefV1
188
- evidenceLevel: EvidenceLevelV1
189
- factRefs: FactRefV1[]
170
+ export interface LoadedOfferFact {
171
+ offerRef: string
172
+ offerVersionRef: string
173
+ hotelRef: string
174
+ evidenceLevel: EvidenceLevel
175
+ factRefs: string[]
190
176
  }
191
177
 
192
- export interface BookingWorkspaceSnapshotV1 {
193
- schemaVersion: typeof BOOKING_SURFACE_SCHEMA_VERSION
194
- contextRef: ContextRefV1
195
- surface: BookingSurfaceV1
196
- revision: number
197
- locale: string
198
- currency: string
199
- searchDraft: SearchDraftSnapshotV1
200
- results: ResultViewSnapshotV1
201
- visibleHotels: VisibleHotelFactV1[]
202
- loadedOffers: LoadedOfferFactV1[]
203
- focusedHotelRef?: HotelRefV1
204
- shortlistedOfferRefs: OfferRefV1[]
205
- selectedOfferRef?: OfferRefV1
206
- verifiedOfferRef?: VerifiedOfferRefV1
207
- capabilities: SurfaceCapabilitiesV1
178
+ export interface VerifiedOfferCapability {
179
+ offerRef: string
180
+ offerVersionRef: string
181
+ verifiedOfferRef: string
182
+ expiresAt: string
208
183
  }
209
184
 
210
- /**
211
- * Browser bootstrap snapshot before the same-origin BFF binds an actor and
212
- * mints contextRef/capabilities. It deliberately cannot assert any identity or
213
- * capability field.
214
- */
215
- export type BookingWorkspaceIngressSnapshotV1 = Omit<
216
- BookingWorkspaceSnapshotV1,
217
- 'contextRef' | 'surface' | 'capabilities'
218
- >
185
+ export interface CriterionBlocker {
186
+ blockerId: string
187
+ sourceActionId: string
188
+ sourceReceiptDigest: string
189
+ scope: BookingBlockerScope
190
+ code: BookingBlockerCode
191
+ criterionPath: string
192
+ strength: 'must'
193
+ valueDigest: string
194
+ valueLabel?: string
195
+ evidence: { factRefs: string[]; gapCodes: BookingGapCode[]; requested?: number; actual?: number }
196
+ }
197
+
198
+ export interface RelaxationApproval {
199
+ taskId: string
200
+ contextRef: string
201
+ sourceTurnId: string
202
+ presentationRequestKey: string
203
+ optionDigest: string
204
+ approvalId: string
205
+ deliveryNonce: string
206
+ blockerId: string
207
+ sourceActionId: string
208
+ sourceReceiptDigest: string
209
+ scope: BookingBlockerScope
210
+ code: BookingBlockerCode
211
+ criterionPath: string
212
+ valueDigest: string
213
+ from: 'must'
214
+ to: 'prefer' | 'drop'
215
+ approved: true
216
+ }
219
217
 
220
- interface BookingReadActionBaseV1<K extends BookingReadActionKindV1, I> {
218
+ export interface RelaxationApprovalRef {
219
+ approvalId: string
220
+ blockerId: string
221
+ contextRef: string
222
+ sourceTurnId: string
223
+ presentationRequestKey: string
224
+ sourceActionId: string
225
+ targetActionId: string
226
+ sourceRevision: number
227
+ targetActionKind: BookingReadActionKind
228
+ to: 'prefer' | 'drop'
229
+ expiresAt: string
230
+ nonce: string
231
+ sourceReceiptDigest: string
232
+ scope: BookingBlockerScope
233
+ code: BookingBlockerCode
234
+ criterionPath: string
235
+ valueDigest: string
236
+ }
237
+
238
+ interface BookingReadActionBase<K extends BookingReadActionKind, I> {
221
239
  schemaVersion: typeof BOOKING_SURFACE_SCHEMA_VERSION
222
240
  kind: K
223
241
  actionId: string
224
- contextRef: ContextRefV1
242
+ contextRef: string
225
243
  expectedRevision: number
226
244
  reason: string
227
- factRefs: FactRefV1[]
245
+ factRefs: string[]
228
246
  input: I
247
+ relaxationApprovalRef?: RelaxationApprovalRef
248
+ }
249
+
250
+ export type SearchPatchAction = BookingReadActionBase<'search.patch', { patch: SearchCriteriaPatch }>
251
+ export type SearchRunAction = BookingReadActionBase<'search.run', Record<string, never>>
252
+ export type ResultsViewPatchAction = BookingReadActionBase<'results.view.patch', { patch: ResultsViewPatch }>
253
+ export type HotelFocusAction = BookingReadActionBase<'hotel.focus', { hotelRef: string }>
254
+ export type HotelSelectAction = BookingReadActionBase<'hotel.select', { hotelRef: string }>
255
+ export type OffersQueryAction = BookingReadActionBase<'offers.query', { hotelRefs: string[]; criteria: OfferCriteria }>
256
+ export type OffersViewPatchAction = BookingReadActionBase<'offers.view.patch', { hotelRef: string; criteria: OfferCriteria }>
257
+ export type OffersCompareAction = BookingReadActionBase<'offers.compare', { offerRefs: string[]; requestedCount: number }>
258
+ export type OfferSelectAction = BookingReadActionBase<'offer.select', { offerRef: string; offerVersionRef: string }>
259
+ export type OfferCheckAction = BookingReadActionBase<'offer.check', { offerRef: string; offerVersionRef: string }>
260
+ export type CheckoutPrepareAction = BookingReadActionBase<'checkout.prepare', { offerRef: string; offerVersionRef: string; verifiedOfferRef: string }>
261
+ export type OrderObserveAction = BookingReadActionBase<'order.observe', { orderRef: string }>
262
+
263
+ export type BookingReadAction =
264
+ | SearchPatchAction
265
+ | SearchRunAction
266
+ | ResultsViewPatchAction
267
+ | HotelFocusAction
268
+ | HotelSelectAction
269
+ | OffersQueryAction
270
+ | OffersViewPatchAction
271
+ | OffersCompareAction
272
+ | OfferSelectAction
273
+ | OfferCheckAction
274
+ | CheckoutPrepareAction
275
+ | OrderObserveAction
276
+
277
+ export interface BookingWorkspaceSnapshot {
278
+ schemaVersion: typeof BOOKING_SURFACE_SCHEMA_VERSION
279
+ contextRef: string
280
+ surface: BookingSurface
281
+ revision: number
282
+ locale: string
283
+ currency: string
284
+ searchDraft: SearchDraftSnapshot
285
+ results: ResultViewSnapshot
286
+ visibleHotels: VisibleHotelFact[]
287
+ loadedOffers: LoadedOfferFact[]
288
+ focusedHotelRef?: string
289
+ shortlistedOfferRefs: string[]
290
+ selectedOfferRef?: string
291
+ verifiedOffer?: VerifiedOfferCapability
292
+ capabilities: { surface: BookingSurface; allowedActions: BookingReadActionKind[] }
229
293
  }
230
294
 
231
- export type SearchPatchActionV1 = BookingReadActionBaseV1<'search.patch', { patch: SearchCriteriaPatchV1 }>
232
- export type SearchRunActionV1 = BookingReadActionBaseV1<'search.run', Record<string, never>>
233
- export type ResultsViewPatchActionV1 = BookingReadActionBaseV1<'results.view.patch', { patch: ResultsViewPatchV1 }>
234
- export type HotelFocusActionV1 = BookingReadActionBaseV1<'hotel.focus', { hotelRef: HotelRefV1 }>
235
- export type HotelSelectActionV1 = BookingReadActionBaseV1<'hotel.select', { hotelRef: HotelRefV1 }>
236
- export type OffersQueryActionV1 = BookingReadActionBaseV1<'offers.query', { hotelRefs: HotelRefV1[]; criteria: OfferCriteriaV1 }>
237
- export type OffersViewPatchActionV1 = BookingReadActionBaseV1<'offers.view.patch', { hotelRef: HotelRefV1; criteria: OfferCriteriaV1 }>
238
- export type OffersCompareActionV1 = BookingReadActionBaseV1<'offers.compare', { offerRefs: OfferRefV1[]; requestedCount: number }>
239
- export type OfferSelectActionV1 = BookingReadActionBaseV1<'offer.select', { offerRef: OfferRefV1 }>
240
- export type OfferCheckActionV1 = BookingReadActionBaseV1<'offer.check', { offerRef: OfferRefV1 }>
241
- export type CheckoutPrepareActionV1 = BookingReadActionBaseV1<'checkout.prepare', { offerRef: OfferRefV1; verifiedOfferRef: VerifiedOfferRefV1 }>
242
- export type OrderObserveActionV1 = BookingReadActionBaseV1<'order.observe', { orderRef: OrderRefV1 }>
243
-
244
- export type BookingReadActionV1 =
245
- | SearchPatchActionV1
246
- | SearchRunActionV1
247
- | ResultsViewPatchActionV1
248
- | HotelFocusActionV1
249
- | HotelSelectActionV1
250
- | OffersQueryActionV1
251
- | OffersViewPatchActionV1
252
- | OffersCompareActionV1
253
- | OfferSelectActionV1
254
- | OfferCheckActionV1
255
- | CheckoutPrepareActionV1
256
- | OrderObserveActionV1
257
-
258
- export type ActionObservationV1 =
259
- | { kind: 'search.state'; searchSessionRef?: string; resultCount?: number }
260
- | { kind: 'results.state'; matchedHotelRefs: HotelRefV1[]; visibleCount: number }
261
- | { kind: 'hotel.focus'; hotelRef: HotelRefV1 }
262
- | { kind: 'hotel.selection'; hotelRef: HotelRefV1 }
263
- | { kind: 'offers.state'; hotelRefs: HotelRefV1[]; offerRefs: OfferRefV1[]; loadedHotelCount: number }
264
- | { kind: 'offer.selection'; offerRef: OfferRefV1 }
265
- | { kind: 'offer.availability'; offerRef: OfferRefV1; verifiedOfferRef?: VerifiedOfferRefV1; available: boolean; changedFactRefs: FactRefV1[] }
266
- | { kind: 'checkout.handoff'; offerRef: OfferRefV1; verifiedOfferRef: VerifiedOfferRefV1; handoffRef: string }
267
- | { kind: 'order.state'; orderRef: OrderRefV1; state: 'pending' | 'verified' | 'failed' | 'unknown' }
268
- | { kind: 'gap'; code: string; factRefs: FactRefV1[] }
269
-
270
- export interface ResultContractV1 {
295
+ export type BookingWorkspaceIngressSnapshot = Pick<
296
+ BookingWorkspaceSnapshot,
297
+ 'schemaVersion' | 'revision' | 'locale' | 'currency' | 'searchDraft' | 'results' | 'visibleHotels' | 'loadedOffers' | 'focusedHotelRef' | 'shortlistedOfferRefs' | 'selectedOfferRef'
298
+ >
299
+
300
+ export type ActionObservation =
301
+ | { kind: 'search.state'; searchSessionRef?: string; resultCount?: number; gapCodes?: BookingGapCode[] }
302
+ | { kind: 'results.state'; matchedHotelRefs: string[]; visibleCount: number; gapCodes?: BookingGapCode[] }
303
+ | { kind: 'hotel.focus'; hotelRef: string }
304
+ | { kind: 'hotel.selection'; hotelRef: string }
305
+ | { kind: 'offers.state'; hotelRefs: string[]; offerRefs: string[]; loadedHotelCount: number; gapCodes?: BookingGapCode[] }
306
+ | { kind: 'offer.selection'; offerRef: string; offerVersionRef: string }
307
+ | { kind: 'offer.availability'; offerRef: string; checkedOfferVersionRef: string; currentOfferVersionRef?: string; verifiedOfferRef?: string; available: boolean; changedFactRefs: string[]; gapCodes?: BookingGapCode[] }
308
+ | { kind: 'checkout.handoff'; offerRef: string; offerVersionRef: string; verifiedOfferRef: string; handoffRef: string }
309
+ | { kind: 'order.state'; orderRef: string; state: 'pending' | 'verified' | 'failed' | 'unknown'; gapCodes?: BookingGapCode[] }
310
+ | { kind: 'gap'; code: BookingGapCode; factRefs: string[] }
311
+
312
+ export interface ResultContract {
271
313
  outcome: 'complete' | 'partial' | 'empty'
272
314
  requestedCount?: number
273
315
  actualCount?: number
274
316
  hardCriteriaMet: boolean
275
- factRefs: FactRefV1[]
276
- gapCodes: string[]
317
+ factRefs: string[]
318
+ gapCodes: BookingGapCode[]
319
+ blockers: CriterionBlocker[]
320
+ relaxationsApplied: RelaxationApproval[]
277
321
  }
278
322
 
279
- export interface ActionReceiptV1 {
323
+ export interface ActionReceipt {
280
324
  schemaVersion: typeof BOOKING_SURFACE_SCHEMA_VERSION
281
325
  kind: 'action.receipt'
282
326
  actionId: string
283
- contextRef: ContextRefV1
284
- status: ActionReceiptStatusV1
327
+ contextRef: string
328
+ status: 'applied' | 'needs_input' | 'partial' | 'no_match' | 'unavailable' | 'changed' | 'stale' | 'unsupported' | 'failed'
285
329
  revision: number
286
- observation: ActionObservationV1
287
- resultContract: ResultContractV1
330
+ observation: ActionObservation
331
+ resultContract: ResultContract
288
332
  undoToken?: string
289
333
  }
290
334
 
291
- export interface UserTurnV1 {
335
+ export interface UserTurn {
292
336
  schemaVersion: typeof BOOKING_SURFACE_SCHEMA_VERSION
293
337
  kind: 'user.turn'
294
- taskId?: string
295
- workspace: BookingWorkspaceSnapshotV1
296
- request: {
297
- /** Transport-only natural language. It must never be persisted as executable state. */
298
- text: string
299
- }
338
+ taskId: string
339
+ turnId: string
340
+ workspace: BookingWorkspaceSnapshot
341
+ request: { text: string; approval?: RelaxationApproval }
300
342
  }
301
343
 
302
- export interface BookingCopilotIngressTurnV1 {
344
+ /** Browser-to-BFF ingress. Identity is deliberately absent from this shape. */
345
+ export interface IngressTurn {
303
346
  schemaVersion: typeof BOOKING_SURFACE_SCHEMA_VERSION
304
347
  kind: 'user.turn.ingress'
305
- taskId?: string
306
- /** Bootstrap may omit this field or send null. A browser cannot mint it. */
307
- contextRef?: null
308
- surfaceHint: BookingSurfaceV1
309
- workspace: BookingWorkspaceIngressSnapshotV1
310
- request: {
311
- text: string
312
- }
348
+ requestKey: BookingRequestKey
349
+ taskHandle?: string
350
+ surfaceHint: BookingSurface
351
+ workspace: BookingWorkspaceIngressSnapshot
352
+ request: { text: string; approval?: RelaxationApproval }
313
353
  }
314
354
 
315
- export interface ActionReceiptContinuationV1 {
355
+ export interface ReceiptContinuation {
316
356
  schemaVersion: typeof BOOKING_SURFACE_SCHEMA_VERSION
317
357
  kind: 'action.receipt.continuation'
318
358
  taskId: string
319
- workspace: BookingWorkspaceSnapshotV1
320
- receipt: ActionReceiptV1
359
+ workspace: BookingWorkspaceSnapshot
360
+ receipt: ActionReceipt
321
361
  }
322
362
 
323
- export type BookingCopilotTurnV1 = UserTurnV1 | ActionReceiptContinuationV1
363
+ export type BookingCopilotTurn = UserTurn | IngressTurn | ReceiptContinuation
324
364
 
325
- interface BookingSurfaceEventBaseV1<K extends BookingSurfaceEventKindV1> {
326
- schemaVersion: typeof BOOKING_SURFACE_SCHEMA_VERSION
327
- eventId: string
365
+ /** Typed BFF seam: implementations authenticate ingress and return only
366
+ * server-issued identity. The HTTP adapter constructs the internal UserTurn. */
367
+ export interface BookingIngressIdentityBinding {
328
368
  taskId: string
329
- contextRef: ContextRefV1
330
- sequence: number
331
- emittedAt: string
332
- kind: K
369
+ turnId: string
370
+ contextRef: string
371
+ /** Authoritative BFF surface; never copied from the browser hint. */
372
+ surface: BookingSurface
373
+ /** BFF-authorized closed action subset for this surface. */
374
+ allowedActions: BookingReadActionKind[]
375
+ }
376
+
377
+ export interface BookingIngressPrincipal {
378
+ subject: string
379
+ scope: string
333
380
  }
334
381
 
335
- export type BookingStatusEventV1 = BookingSurfaceEventBaseV1<'status'> & {
336
- status: 'submitted' | 'working' | 'waiting_receipt' | 'input_required'
382
+ export interface BookingIngressBinding {
383
+ bind(input: IngressTurn, principal: BookingIngressPrincipal): BookingIngressIdentityBinding | Promise<BookingIngressIdentityBinding>
337
384
  }
338
385
 
339
- export type BookingQuestionEventV1 = BookingSurfaceEventBaseV1<'question'> & {
386
+ export interface BookingQuestionEvent {
387
+ schemaVersion: typeof BOOKING_SURFACE_SCHEMA_VERSION
388
+ eventId: string
389
+ taskId: string
390
+ contextRef: string
391
+ sequence: number
392
+ emittedAt: string
393
+ kind: 'question'
340
394
  question: {
341
395
  questionId: string
342
396
  prompt: string
343
397
  missingFields: string[]
398
+ type: 'relaxation_approval_required'
399
+ blocker: CriterionBlocker
400
+ approvalOptions: Array<{ approval: RelaxationApproval }>
344
401
  }
345
402
  }
346
403
 
347
- export type BookingOperationEventV1 = BookingSurfaceEventBaseV1<'operation'> & {
348
- action: BookingReadActionV1
349
- }
350
-
351
- export type BookingExplanationEventV1 = BookingSurfaceEventBaseV1<'explanation'> & {
352
- explanation: {
353
- text: string
354
- factRefs: FactRefV1[]
355
- }
356
- }
357
-
358
- export type BookingTerminalEventV1 = BookingSurfaceEventBaseV1<'terminal'> & {
359
- terminal: {
360
- status: 'completed' | 'stopped'
361
- summary: string
362
- factRefs: FactRefV1[]
363
- }
364
- }
365
-
366
- export type BookingErrorEventV1 = BookingSurfaceEventBaseV1<'error'> & {
367
- error: {
368
- code: string
369
- message: string
370
- retryable: boolean
371
- }
404
+ export interface BookingEventBase {
405
+ schemaVersion: typeof BOOKING_SURFACE_SCHEMA_VERSION
406
+ eventId: string
407
+ taskId: string
408
+ contextRef: string
409
+ sequence: number
410
+ emittedAt: string
372
411
  }
373
412
 
374
- export type BookingSurfaceEventV1 =
375
- | BookingStatusEventV1
376
- | BookingQuestionEventV1
377
- | BookingOperationEventV1
378
- | BookingExplanationEventV1
379
- | BookingTerminalEventV1
380
- | BookingErrorEventV1
413
+ export type BookingSurfaceEvent =
414
+ | (BookingEventBase & { kind: 'status'; status: 'submitted' | 'working' | 'waiting_receipt' | 'input_required' })
415
+ | BookingQuestionEvent
416
+ | (BookingEventBase & { kind: 'operation'; action: BookingReadAction })
417
+ | (BookingEventBase & { kind: 'explanation'; explanation: { text: string; factRefs: string[] } })
418
+ | (BookingEventBase & { kind: 'terminal'; terminal: { status: 'completed' | 'stopped'; summary: string; factRefs: string[] } })
419
+ | (BookingEventBase & { kind: 'error'; error: { code: string; message: string; retryable: boolean } })