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

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 (229) hide show
  1. package/README.md +161 -116
  2. package/README.zh-CN.md +173 -144
  3. package/bin/gotry-booking-copilot.js +53 -0
  4. package/bin/gotry-bootstrap.js +113 -66
  5. package/bin/gotry-inner.js +436 -70
  6. package/bin/gotry-runtime-resolution.d.ts +27 -0
  7. package/bin/gotry-runtime-resolution.js +50 -0
  8. package/bin/gotry.js +1 -1
  9. package/cordis.gotry-patch.yml +5 -1
  10. package/dist/capabilities/agent-reach-deep.js +1 -1
  11. package/dist/capabilities/agent-reach.js +1 -1
  12. package/dist/capabilities/anything.js +1 -1
  13. package/dist/capabilities/artifacts.js +1 -1
  14. package/dist/capabilities/effect.js +1 -1
  15. package/dist/capabilities/fact-log.js +1 -1
  16. package/dist/capabilities/flyai.js +20 -6
  17. package/dist/capabilities/hbcli.js +1 -1
  18. package/dist/capabilities/incident-log.js +1 -1
  19. package/dist/capabilities/model-override.js +18 -0
  20. package/dist/capabilities/opensky.js +1 -1
  21. package/dist/capabilities/resilience.js +1 -1
  22. package/dist/capabilities/session/action-cache.js +1 -1
  23. package/dist/capabilities/session/adapters/ctrip-flight.js +1 -1
  24. package/dist/capabilities/session/adapters/meituan-local.js +1 -1
  25. package/dist/capabilities/session/benchmark.js +1 -1
  26. package/dist/capabilities/session/extension-bridge.js +19 -6
  27. package/dist/capabilities/session/extension-channel.js +3 -3
  28. package/dist/capabilities/session/extension-distribution.js +234 -0
  29. package/dist/capabilities/session/extract.js +1 -1
  30. package/dist/capabilities/session/golden-score.js +92 -0
  31. package/dist/capabilities/session/health-watch.js +1 -1
  32. package/dist/capabilities/session/read-guard.js +1 -1
  33. package/dist/capabilities/session/static-flight-golden.js +137 -0
  34. package/dist/capabilities/session/transport.js +1 -1
  35. package/dist/capabilities/session/wizard.js +21 -251
  36. package/dist/capabilities/session-consent.js +1 -1
  37. package/dist/capabilities/session-login.js +11 -5
  38. package/dist/capabilities/session-search.js +46 -4
  39. package/dist/capabilities/weather.js +168 -46
  40. package/dist/data/session-golden-20.json +25 -0
  41. package/dist/data/sf-golden-manifest.json +102 -0
  42. package/dist/data/sf-static-routes.json +91 -0
  43. package/dist/scripts/action-cache-tests.js +1 -1
  44. package/dist/scripts/agent-planning-budget-e2e.js +227 -0
  45. package/dist/scripts/agent-planning-budget-tests.js +173 -0
  46. package/dist/scripts/agent-reach-deep-tests.js +1 -1
  47. package/dist/scripts/agent-reach-tests.js +1 -1
  48. package/dist/scripts/agent-reach-wrapper-tests.js +1 -1
  49. package/dist/scripts/anything-tests.js +1 -1
  50. package/dist/scripts/async-collect.js +1 -1
  51. package/dist/scripts/benchmark-environment-bridge-e2e.js +981 -0
  52. package/dist/scripts/benchmark-environment-bridge-tests.js +2544 -0
  53. package/dist/scripts/booking-copilot-availability-ledger-binding-tests.js +335 -0
  54. package/dist/scripts/booking-copilot-availability-policy-v2-tests.js +1355 -0
  55. package/dist/scripts/booking-copilot-bin-proof-tests.js +89 -0
  56. package/dist/scripts/booking-copilot-crossrepo-fixture-server.js +113 -0
  57. package/dist/scripts/booking-copilot-dsh-core-proof-tests.js +356 -0
  58. package/dist/scripts/booking-copilot-dsh-planner-proof-tests.js +557 -0
  59. package/dist/scripts/booking-copilot-dsh-plugin-proof-tests.js +140 -0
  60. package/dist/scripts/booking-copilot-event-sequence-concurrency-proof-tests.js +202 -0
  61. package/dist/scripts/booking-copilot-gap-code-contract-proof-tests.js +102 -0
  62. package/dist/scripts/booking-copilot-operation-ledger-concurrency-proof-tests.js +374 -0
  63. package/dist/scripts/booking-copilot-receipt-ledger-concurrency-proof-tests.js +447 -0
  64. package/dist/scripts/booking-copilot-runtime-proof-tests.js +205 -0
  65. package/dist/scripts/booking-copilot-server-proof-tests.js +317 -0
  66. package/dist/scripts/booking-copilot-startup-proof-tests.js +283 -0
  67. package/dist/scripts/booking-copilot-v2-runtime-proof-tests.js +3935 -0
  68. package/dist/scripts/booking-saga-tests.js +1 -1
  69. package/dist/scripts/booking-surface-contract-proof-tests.js +393 -0
  70. package/dist/scripts/booking-surface-v2-contract-proof-tests.js +1174 -0
  71. package/dist/scripts/bootstrap-tests.js +45 -39
  72. package/dist/scripts/build-changelog.js +1 -1
  73. package/dist/scripts/changelog-tests.js +1 -1
  74. package/dist/scripts/companion-tests.js +1 -1
  75. package/dist/scripts/diff-test.js +1 -1
  76. package/dist/scripts/dsh-runtime-closure-tests.js +225 -0
  77. package/dist/scripts/dsh-runtime-closure.js +150 -0
  78. package/dist/scripts/effect-tests.js +1 -1
  79. package/dist/scripts/engine-run.js +1 -1
  80. package/dist/scripts/engine-tests.js +1 -1
  81. package/dist/scripts/evaluation-cadence-tests.js +347 -0
  82. package/dist/scripts/evaluation-contract-tests.js +574 -0
  83. package/dist/scripts/extension-distribution-cli.js +35 -0
  84. package/dist/scripts/extension-distribution-tests.js +341 -0
  85. package/dist/scripts/extension-tests.js +128 -23
  86. package/dist/scripts/fact-gate-tests.js +1 -1
  87. package/dist/scripts/flyai-tests.js +1 -1
  88. package/dist/scripts/hbcli-e2e-tests.js +1 -1
  89. package/dist/scripts/hbcli-tests.js +1 -1
  90. package/dist/scripts/health-watch-cli.js +1 -1
  91. package/dist/scripts/i18n-tests.js +1 -1
  92. package/dist/scripts/incident-tests.js +1 -1
  93. package/dist/scripts/journey-tests.js +1 -1
  94. package/dist/scripts/ledger-tests.js +1 -1
  95. package/dist/scripts/ledger-workflow-crash.js +1 -1
  96. package/dist/scripts/memory-capture-tests.js +1 -1
  97. package/dist/scripts/memory-decay-tests.js +1 -1
  98. package/dist/scripts/memory-metrics.js +1 -1
  99. package/dist/scripts/memory-value-report.js +1 -1
  100. package/dist/scripts/model-override-e2e.js +176 -0
  101. package/dist/scripts/nightly-evidence-tests.js +1 -1
  102. package/dist/scripts/nightly-evidence.js +1 -1
  103. package/dist/scripts/nudge-digest.js +1 -1
  104. package/dist/scripts/onboarding-tests.js +21 -53
  105. package/dist/scripts/opensky-check.js +1 -1
  106. package/dist/scripts/opensky-tests.js +1 -1
  107. package/dist/scripts/pnpm-dsh-closure-proof.js +20 -0
  108. package/dist/scripts/price-drift-tests.js +1 -1
  109. package/dist/scripts/price-drift-watch.js +1 -1
  110. package/dist/scripts/probe-poi-tests.js +1 -1
  111. package/dist/scripts/product-metrics.js +1 -1
  112. package/dist/scripts/publish-preverify.js +40 -4
  113. package/dist/scripts/realtime-pricing-tests.js +1 -1
  114. package/dist/scripts/replay-async.js +1 -1
  115. package/dist/scripts/replay-real.js +1 -1
  116. package/dist/scripts/replay.js +1 -1
  117. package/dist/scripts/session-attach-diagnose.js +1 -1
  118. package/dist/scripts/session-attach-poc.js +1 -1
  119. package/dist/scripts/session-benchmark.js +1 -1
  120. package/dist/scripts/session-extract-tests.js +1 -1
  121. package/dist/scripts/session-login.js +1 -1
  122. package/dist/scripts/session-tests.js +70 -20
  123. package/dist/scripts/sf-live-benchmark.js +338 -0
  124. package/dist/scripts/sf-live-cli-tests.js +21 -0
  125. package/dist/scripts/sf-soft-score-tests.js +108 -0
  126. package/dist/scripts/sf-summary.js +93 -0
  127. package/dist/scripts/skeleton-check.js +1 -1
  128. package/dist/scripts/skeleton-integration-test.js +1 -1
  129. package/dist/scripts/skills-contract-tests.js +1 -1
  130. package/dist/scripts/smoke-session-gate-tests.js +29 -0
  131. package/dist/scripts/smoke.js +79 -33
  132. package/dist/scripts/state-cli-tests.js +1 -1
  133. package/dist/scripts/state-cli.js +1 -1
  134. package/dist/scripts/static-golden-tests.js +299 -0
  135. package/dist/scripts/time-eval-tests.js +1 -1
  136. package/dist/scripts/travel-timeline-tests.js +1 -1
  137. package/dist/scripts/unified-tests.js +1 -1
  138. package/dist/scripts/weather-tests.js +694 -44
  139. package/dist/scripts/z3-race-tests.js +1 -1
  140. package/dist/src/artifact-gate.js +1 -1
  141. package/dist/src/benchmark-agent-conformance.js +370 -0
  142. package/dist/src/benchmark-environment-bridge.js +384 -0
  143. package/dist/src/benchmark-headless-child-diagnostics.js +173 -0
  144. package/dist/src/benchmark-tool-isolation.js +124 -0
  145. package/dist/src/bookable-facts.js +1 -1
  146. package/dist/src/booking-saga.js +1 -1
  147. package/dist/src/booking-surface/availability-policy-v2.js +830 -0
  148. package/dist/src/booking-surface/canonical-schema.js +113 -0
  149. package/dist/src/booking-surface/contracts-v2.js +89 -0
  150. package/dist/src/booking-surface/contracts.js +46 -0
  151. package/dist/src/booking-surface/dsh-planner.js +453 -0
  152. package/dist/src/booking-surface/dsh-plugin.js +93 -0
  153. package/dist/src/booking-surface/error-codes.js +94 -0
  154. package/dist/src/booking-surface/index.js +15 -0
  155. package/dist/src/booking-surface/profile.js +68 -0
  156. package/dist/src/booking-surface/runtime-v2.js +1771 -0
  157. package/dist/src/booking-surface/runtime.js +351 -0
  158. package/dist/src/booking-surface/server-v2.js +334 -0
  159. package/dist/src/booking-surface/server.js +302 -0
  160. package/dist/src/booking-surface/startup.js +159 -0
  161. package/dist/src/booking-surface/validation-v2.js +319 -0
  162. package/dist/src/booking-surface/validation.js +809 -0
  163. package/dist/src/bridge.js +1 -1
  164. package/dist/src/companions.js +1 -1
  165. package/dist/src/contracts.js +1 -1
  166. package/dist/src/dsh-llm.js +1 -1
  167. package/dist/src/engine.js +1 -1
  168. package/dist/src/evaluation-cadence.js +234 -0
  169. package/dist/src/evaluation-contracts.js +906 -0
  170. package/dist/src/i18n.js +1 -1
  171. package/dist/src/index.js +50 -19
  172. package/dist/src/journey.js +1 -1
  173. package/dist/src/loop.js +1 -1
  174. package/dist/src/memory-capture.js +1 -1
  175. package/dist/src/memory-decay.js +1 -1
  176. package/dist/src/memory-utility.js +1 -1
  177. package/dist/src/mock-llm.js +1 -1
  178. package/dist/src/model.js +1 -1
  179. package/dist/src/realtime-pricing.js +1 -1
  180. package/dist/src/slot-spec.js +1 -1
  181. package/dist/src/state-ledger.js +2 -1
  182. package/dist/src/time-anchor.js +1 -1
  183. package/dist/src/tool-budget.js +136 -0
  184. package/dist/src/tool-packet.js +1 -1
  185. package/dist/src/travel-slots.js +1 -1
  186. package/dist/src/travel-timeline.js +1 -1
  187. package/dist/src/unified.js +1 -1
  188. package/dist/src/wish-pool.js +1 -1
  189. package/dist/src/z3-shared.js +1 -1
  190. package/extension/README.md +31 -7
  191. package/package.json +286 -11
  192. package/schemas/booking.surface.v1.schema.json +927 -0
  193. package/schemas/booking.surface.v2.schema.json +61 -0
  194. package/ts/capabilities/flyai.ts +16 -3
  195. package/ts/capabilities/session/extension-bridge.ts +37 -14
  196. package/ts/capabilities/session/extension-channel.ts +6 -3
  197. package/ts/capabilities/session/extension-distribution.ts +264 -0
  198. package/ts/capabilities/session/golden-score.ts +139 -0
  199. package/ts/capabilities/session/health-watch.ts +1 -1
  200. package/ts/capabilities/session/static-flight-golden.ts +209 -0
  201. package/ts/capabilities/session/wizard.ts +34 -176
  202. package/ts/capabilities/session-login.ts +15 -5
  203. package/ts/capabilities/session-search.ts +40 -3
  204. package/ts/capabilities/weather.ts +141 -52
  205. package/ts/package.json +3 -3
  206. package/ts/src/benchmark-agent-conformance.ts +448 -0
  207. package/ts/src/benchmark-environment-bridge.ts +348 -0
  208. package/ts/src/benchmark-headless-child-diagnostics.ts +184 -0
  209. package/ts/src/benchmark-tool-isolation.ts +166 -0
  210. package/ts/src/booking-surface/availability-policy-v2.ts +523 -0
  211. package/ts/src/booking-surface/canonical-schema.js +113 -0
  212. package/ts/src/booking-surface/contracts-v2.ts +118 -0
  213. package/ts/src/booking-surface/contracts.ts +380 -0
  214. package/ts/src/booking-surface/dsh-planner.ts +452 -0
  215. package/ts/src/booking-surface/dsh-plugin.js +93 -0
  216. package/ts/src/booking-surface/error-codes.ts +101 -0
  217. package/ts/src/booking-surface/index.ts +12 -0
  218. package/ts/src/booking-surface/profile.ts +42 -0
  219. package/ts/src/booking-surface/runtime-v2.ts +1466 -0
  220. package/ts/src/booking-surface/runtime.ts +483 -0
  221. package/ts/src/booking-surface/server-v2.ts +247 -0
  222. package/ts/src/booking-surface/server.ts +324 -0
  223. package/ts/src/booking-surface/startup.ts +196 -0
  224. package/ts/src/booking-surface/validation-v2.ts +205 -0
  225. package/ts/src/booking-surface/validation.ts +453 -0
  226. package/ts/src/index.ts +64 -11
  227. package/ts/src/state-ledger.ts +1 -0
  228. package/ts/src/tool-budget.ts +165 -0
  229. package/dist/scripts/wizard-bootstrap.js +0 -32
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Runtime projection of the canonical booking.surface.v1 JSON Schema.
3
+ *
4
+ * dsh tools need self-contained JSON Schemas, while the canonical document is
5
+ * organized with local $refs. This helper derives each action branch directly
6
+ * from those canonical bytes and recursively inlines local references. No
7
+ * model-facing action schema is maintained by hand.
8
+ */
9
+
10
+ import { readFileSync } from 'node:fs'
11
+
12
+ const schemaUrl = new URL('../../../schemas/booking.surface.v1.schema.json', import.meta.url)
13
+ export const canonicalBookingSurfaceSchemaV1 = JSON.parse(readFileSync(schemaUrl, 'utf8'))
14
+ const schemaV2Url = new URL('../../../schemas/booking.surface.v2.schema.json', import.meta.url)
15
+ export const canonicalBookingSurfaceSchemaV2 = JSON.parse(readFileSync(schemaV2Url, 'utf8'))
16
+
17
+ function clone(value) {
18
+ return JSON.parse(JSON.stringify(value))
19
+ }
20
+
21
+ function definitionFromRef(ref, schema) {
22
+ const prefix = '#/$defs/'
23
+ if (typeof ref !== 'string') {
24
+ throw new Error(`booking_schema_external_ref_forbidden:${String(ref)}`)
25
+ }
26
+ const externalV1 = 'https://gotry.dev/schemas/booking.surface.v1.schema.json#/$defs/'
27
+ const definitionSchema = ref.startsWith(prefix) ? schema : ref.startsWith(externalV1) ? canonicalBookingSurfaceSchemaV1 : undefined
28
+ if (!definitionSchema) throw new Error(`booking_schema_external_ref_forbidden:${String(ref)}`)
29
+ const name = ref.startsWith(prefix) ? ref.slice(prefix.length) : ref.slice(externalV1.length)
30
+ const definition = definitionSchema.$defs?.[name]
31
+ if (!definition) throw new Error(`booking_schema_missing_definition:${name}`)
32
+ return definition
33
+ }
34
+
35
+ function inlineLocalRefs(value, schema, stack = []) {
36
+ if (Array.isArray(value)) return value.map((item) => inlineLocalRefs(item, schema, stack))
37
+ if (typeof value !== 'object' || value === null) return value
38
+ if (typeof value.$ref === 'string') {
39
+ if (stack.includes(value.$ref)) throw new Error(`booking_schema_recursive_ref:${value.$ref}`)
40
+ const { $ref, ...siblings } = value
41
+ const definitionSchema = typeof $ref === 'string' && $ref.startsWith('https://gotry.dev/schemas/booking.surface.v1.schema.json#/$defs/') ? canonicalBookingSurfaceSchemaV1 : schema
42
+ return {
43
+ ...inlineLocalRefs(definitionFromRef($ref, schema), definitionSchema, [...stack, $ref]),
44
+ ...inlineLocalRefs(siblings, schema, stack),
45
+ }
46
+ }
47
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, inlineLocalRefs(item, schema, stack)]))
48
+ }
49
+
50
+ function canonicalActionSchemaForKind(kind, schema, definitionName) {
51
+ const action = schema.$defs?.[definitionName]
52
+ if (!action) throw new Error('booking_schema_action_union_missing')
53
+ if (Array.isArray(action.allOf)) {
54
+ const branch = action.allOf.find((candidate) => candidate?.if?.properties?.kind?.const === kind)
55
+ const input = branch?.then?.properties?.input
56
+ if (!input) throw new Error(`booking_schema_action_kind_missing:${kind}`)
57
+ return clone(inlineLocalRefs({
58
+ type: action.type,
59
+ required: action.required,
60
+ properties: { ...action.properties, kind: { type: 'string', const: kind }, input },
61
+ additionalProperties: action.additionalProperties,
62
+ }, schema))
63
+ }
64
+ if (!Array.isArray(action.oneOf)) throw new Error('booking_schema_action_union_missing')
65
+ const branch = action.oneOf.find((candidate) => candidate?.allOf?.some((part) => part?.properties?.kind?.const === kind))
66
+ const base = schema.$defs?.ActionBase
67
+ const input = branch?.allOf?.find((part) => part?.properties?.input)?.properties?.input
68
+ if (!base || !input) throw new Error(`booking_schema_action_kind_missing:${kind}`)
69
+ return clone(inlineLocalRefs({
70
+ ...base,
71
+ properties: { ...base.properties, kind: { type: 'string', const: kind }, input },
72
+ }, schema))
73
+ }
74
+
75
+ export function canonicalBookingActionSchemaForKind(kind) {
76
+ return canonicalActionSchemaForKind(kind, canonicalBookingSurfaceSchemaV1, 'BookingReadActionV1')
77
+ }
78
+
79
+ export function canonicalBookingActionSchemaForKindV2(kind) {
80
+ return canonicalActionSchemaForKind(kind, canonicalBookingSurfaceSchemaV2, 'Action')
81
+ }
82
+
83
+ const DSH_JSON_SCHEMA_KEYS = new Set([
84
+ 'type', 'oneOf', 'properties', 'required', 'additionalProperties', 'items',
85
+ 'enum', 'const', 'description', 'title', 'default', 'examples',
86
+ ])
87
+
88
+ function projectDshSchema(value) {
89
+ if (Array.isArray(value)) return value.map(projectDshSchema)
90
+ if (typeof value !== 'object' || value === null) return value
91
+ return Object.fromEntries(Object.entries(value)
92
+ .filter(([key]) => DSH_JSON_SCHEMA_KEYS.has(key))
93
+ .map(([key, item]) => {
94
+ if (key === 'properties') {
95
+ return [key, Object.fromEntries(Object.entries(item).map(([name, property]) => [name, projectDshSchema(property)]))]
96
+ }
97
+ return [key, projectDshSchema(item)]
98
+ }))
99
+ }
100
+
101
+ /**
102
+ * dsh-tools intentionally supports a smaller enforced JSON-Schema vocabulary.
103
+ * Keep the canonical shape/type/enum/closure guarantees at the model seam;
104
+ * the full canonical AJV validator remains the runtime authority for numeric,
105
+ * pattern, size and uniqueness constraints before an operation can be issued.
106
+ */
107
+ export function dshBookingActionSchemaForKind(kind) {
108
+ return projectDshSchema(canonicalBookingActionSchemaForKind(kind))
109
+ }
110
+
111
+ export function dshBookingActionSchemaForKindV2(kind) {
112
+ return projectDshSchema(canonicalBookingActionSchemaForKindV2(kind))
113
+ }
@@ -0,0 +1,118 @@
1
+ import type { BookingReadActionKindV1, BookingWorkspaceSnapshotV1, SearchCriteriaPatchV1, ResultsViewPatchV1, OfferCriteriaV1, EvidenceLevelV1 } from './contracts.ts'
2
+
3
+ export const BOOKING_SURFACE_SCHEMA_VERSION_V2 = 'booking.surface.v2' as const
4
+ /**
5
+ * Process composition modes are deliberately separate from the payload
6
+ * schema. The default accepts turns already bound by HotelByte's BFF; the
7
+ * second mode is reserved for an in-process BFF binding seam.
8
+ */
9
+ export const BOOKING_COPILOT_V2_INGRESS_MODES = ['bff-bound-turn-only', 'bff-ingress-binding'] as const
10
+ export type BookingCopilotV2IngressMode = typeof BOOKING_COPILOT_V2_INGRESS_MODES[number]
11
+ export const BOOKING_COPILOT_V2_ACCEPTED_TURN_KINDS = ['user.turn', 'action.receipt.continuation'] as const
12
+ export const BOOKING_COPILOT_V2_INGRESS_TURN_KIND = 'user.turn.ingress' as const
13
+ /** Hard task-level operation budget. The counter is persisted in the v2 ledger. */
14
+ export const BOOKING_COPILOT_MAX_OPERATIONS_V2 = 20 as const
15
+ export const BOOKING_SURFACE_SCHEMA_V2_SHA256 = '45df62db1b19d30a4fd22ddc94eb550e8ff32d8a225558b5ff13ba303588fc03' as const
16
+ export const BOOKING_READ_ACTION_KINDS_V2 = ['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 satisfies readonly BookingReadActionKindV1[]
17
+ export type BookingReadActionKindV2 = typeof BOOKING_READ_ACTION_KINDS_V2[number]
18
+ export type BookingSurfaceV2 = 'tenant' | 'customer_portal' | 'storefront' | 'payment_link'
19
+ /** Product-owned least-privilege action matrix. BFF bindings may narrow these lists, never expand them. */
20
+ export const BOOKING_SURFACE_ALLOWED_ACTIONS_V2: Record<BookingSurfaceV2, readonly BookingReadActionKindV2[]> = {
21
+ tenant: BOOKING_READ_ACTION_KINDS_V2,
22
+ customer_portal: BOOKING_READ_ACTION_KINDS_V2,
23
+ storefront: ['search.patch', 'search.run', 'results.view.patch', 'hotel.focus'],
24
+ payment_link: ['search.patch', 'search.run', 'results.view.patch', 'hotel.focus', 'hotel.select'],
25
+ }
26
+ /** Stable product-matrix observation for UAT and server readiness proofs. */
27
+ export function bookingSurfaceAllowedActionsV2(surface: BookingSurfaceV2): BookingReadActionKindV2[] {
28
+ return [...BOOKING_SURFACE_ALLOWED_ACTIONS_V2[surface]]
29
+ }
30
+ export type BookingRequestKeyV2 = string
31
+ /** Runtime-owned idempotency key; this is not a browser request key. */
32
+ export type BookingInternalDecisionKeyV2 = string
33
+ export const BOOKING_V2_BLOCKER_CODES = ['no_hotels_matched','hotel_not_visible','hotel_rates_failed','criterion_must_not_met','offer_target_not_reached','offer_unavailable'] as const
34
+ export type BookingV2BlockerCode = typeof BOOKING_V2_BLOCKER_CODES[number]
35
+ export const BOOKING_V2_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
36
+ export type BookingV2GapCode = typeof BOOKING_V2_GAP_CODES[number]
37
+ export type BookingV2BlockerScope = 'search' | 'offer' | 'availability' | 'checkout'
38
+ export interface CriterionBlockerV2 { blockerId: string; sourceActionId: string; sourceReceiptDigest: string; scope: BookingV2BlockerScope; code: BookingV2BlockerCode; criterionPath: string; strength: 'must'; valueDigest: string; valueLabel?: string; evidence: { factRefs: string[]; gapCodes: BookingV2GapCode[]; requested?: number; actual?: number } }
39
+ export interface RelaxationApprovalV2 {
40
+ taskId: string
41
+ contextRef: string
42
+ sourceTurnId: string
43
+ presentationRequestKey: string
44
+ optionDigest: string
45
+ approvalId: string
46
+ deliveryNonce: string
47
+ blockerId: string
48
+ sourceActionId: string
49
+ sourceReceiptDigest: string
50
+ scope: BookingV2BlockerScope
51
+ code: BookingV2BlockerCode
52
+ criterionPath: string
53
+ valueDigest: string
54
+ from: 'must'
55
+ to: 'prefer' | 'drop'
56
+ approved: true
57
+ }
58
+ export interface RelaxationApprovalRefV2 { approvalId: string; blockerId: string; contextRef: string; sourceTurnId: string; presentationRequestKey: string; sourceActionId: string; targetActionId: string; sourceRevision: number; targetActionKind: BookingReadActionKindV2; to: 'prefer'|'drop'; expiresAt: string; nonce: string; sourceReceiptDigest: string; scope: BookingV2BlockerScope; code: BookingV2BlockerCode; criterionPath: string; valueDigest: string }
59
+ interface Base<K extends BookingReadActionKindV2, I> { schemaVersion: typeof BOOKING_SURFACE_SCHEMA_VERSION_V2; kind: K; actionId: string; contextRef: string; expectedRevision: number; reason: string; factRefs: string[]; input: I; relaxationApprovalRef?: RelaxationApprovalRefV2 }
60
+ export type SearchPatchActionV2 = Base<'search.patch', { patch: SearchCriteriaPatchV1 }>
61
+ export type SearchRunActionV2 = Base<'search.run', Record<string, never>>
62
+ export type ResultsViewPatchActionV2 = Base<'results.view.patch', { patch: ResultsViewPatchV1 }>
63
+ export type HotelFocusActionV2 = Base<'hotel.focus', { hotelRef: string }>
64
+ export type HotelSelectActionV2 = Base<'hotel.select', { hotelRef: string }>
65
+ export type OffersQueryActionV2 = Base<'offers.query', { hotelRefs: string[]; criteria: OfferCriteriaV1 }>
66
+ export type OffersViewPatchActionV2 = Base<'offers.view.patch', { hotelRef: string; criteria: OfferCriteriaV1 }>
67
+ export type OffersCompareActionV2 = Base<'offers.compare', { offerRefs: string[]; requestedCount: number }>
68
+ export interface LoadedOfferFactV2 { offerRef: string; offerVersionRef: string; hotelRef: string; evidenceLevel: EvidenceLevelV1; factRefs: string[] }
69
+ export interface VerifiedOfferCapabilityV2 { offerRef: string; offerVersionRef: string; verifiedOfferRef: string; expiresAt: string }
70
+ export type OfferSelectActionV2 = Base<'offer.select', { offerRef: string; offerVersionRef: string }>
71
+ export type OfferCheckActionV2 = Base<'offer.check', { offerRef: string; offerVersionRef: string }>
72
+ export type CheckoutPrepareActionV2 = Base<'checkout.prepare', { offerRef: string; offerVersionRef: string; verifiedOfferRef: string }>
73
+ export type OrderObserveActionV2 = Base<'order.observe', { orderRef: string }>
74
+ export type BookingReadActionV2=SearchPatchActionV2|SearchRunActionV2|ResultsViewPatchActionV2|HotelFocusActionV2|HotelSelectActionV2|OffersQueryActionV2|OffersViewPatchActionV2|OffersCompareActionV2|OfferSelectActionV2|OfferCheckActionV2|CheckoutPrepareActionV2|OrderObserveActionV2
75
+ export interface BookingWorkspaceSnapshotV2 extends Omit<BookingWorkspaceSnapshotV1,'schemaVersion'|'surface'|'capabilities'|'loadedOffers'|'verifiedOfferRef'>{schemaVersion:typeof BOOKING_SURFACE_SCHEMA_VERSION_V2;surface:BookingSurfaceV2;loadedOffers:LoadedOfferFactV2[];verifiedOffer?:VerifiedOfferCapabilityV2;capabilities:{surface:BookingSurfaceV2;allowedActions:BookingReadActionKindV2[]}}
76
+ export type BookingWorkspaceIngressSnapshotV2 = Pick<BookingWorkspaceSnapshotV2, 'schemaVersion'|'revision'|'locale'|'currency'|'searchDraft'|'results'|'visibleHotels'|'loadedOffers'|'focusedHotelRef'|'shortlistedOfferRefs'|'selectedOfferRef'>
77
+ export type ActionObservationV2 =
78
+ | { kind: 'search.state'; searchSessionRef?: string; resultCount?: number; gapCodes?: BookingV2GapCode[] }
79
+ | { kind: 'results.state'; matchedHotelRefs: string[]; visibleCount: number; gapCodes?: BookingV2GapCode[] }
80
+ | { kind: 'hotel.focus'; hotelRef: string }
81
+ | { kind: 'hotel.selection'; hotelRef: string }
82
+ | { kind: 'offers.state'; hotelRefs: string[]; offerRefs: string[]; loadedHotelCount: number; gapCodes?: BookingV2GapCode[] }
83
+ | { kind: 'offer.selection'; offerRef: string; offerVersionRef: string }
84
+ | { kind: 'offer.availability'; offerRef: string; checkedOfferVersionRef: string; currentOfferVersionRef?: string; verifiedOfferRef?: string; available: boolean; changedFactRefs: string[]; gapCodes?: BookingV2GapCode[] }
85
+ | { kind: 'checkout.handoff'; offerRef: string; offerVersionRef: string; verifiedOfferRef: string; handoffRef: string }
86
+ | { kind: 'order.state'; orderRef: string; state: 'pending'|'verified'|'failed'|'unknown'; gapCodes?: BookingV2GapCode[] }
87
+ | { kind: 'gap'; code: BookingV2GapCode; factRefs: string[] }
88
+ export interface ResultContractV2 {outcome:'complete'|'partial'|'empty';requestedCount?:number;actualCount?:number;hardCriteriaMet:boolean;factRefs:string[];gapCodes:BookingV2GapCode[];blockers:CriterionBlockerV2[];relaxationsApplied:RelaxationApprovalV2[]}
89
+ export interface ActionReceiptV2 {schemaVersion:typeof BOOKING_SURFACE_SCHEMA_VERSION_V2;kind:'action.receipt';actionId:string;contextRef:string;status:'applied'|'needs_input'|'partial'|'no_match'|'unavailable'|'changed'|'stale'|'unsupported'|'failed';revision:number;observation:ActionObservationV2;resultContract:ResultContractV2;undoToken?:string}
90
+ export interface UserTurnV2 {schemaVersion:typeof BOOKING_SURFACE_SCHEMA_VERSION_V2;kind:'user.turn';taskId:string;turnId:string;workspace:BookingWorkspaceSnapshotV2;request:{text:string;approval?:RelaxationApprovalV2}}
91
+ /** Browser-to-BFF ingress. Identity is deliberately absent from this shape. */
92
+ export interface IngressTurnV2 {schemaVersion:typeof BOOKING_SURFACE_SCHEMA_VERSION_V2;kind:'user.turn.ingress';requestKey:BookingRequestKeyV2;taskHandle?:string;surfaceHint:BookingSurfaceV2;workspace:BookingWorkspaceIngressSnapshotV2;request:{text:string}}
93
+ export interface ReceiptContinuationV2 {schemaVersion:typeof BOOKING_SURFACE_SCHEMA_VERSION_V2;kind:'action.receipt.continuation';taskId:string;workspace:BookingWorkspaceSnapshotV2;receipt:ActionReceiptV2}
94
+ export type BookingCopilotTurnV2=UserTurnV2|IngressTurnV2|ReceiptContinuationV2
95
+ /** Typed BFF seam: implementations authenticate ingress and return only
96
+ * server-issued identity. The HTTP adapter constructs the internal UserTurn. */
97
+ export interface BookingIngressIdentityBindingV2 {
98
+ taskId: string
99
+ turnId: string
100
+ contextRef: string
101
+ /** Authoritative BFF surface; never copied from the browser hint. */
102
+ surface: BookingSurfaceV2
103
+ /** BFF-authorized closed action subset for this surface. */
104
+ allowedActions: BookingReadActionKindV2[]
105
+ }
106
+ export interface BookingIngressPrincipalV2 { subject: string; scope: string }
107
+ export interface BookingIngressBindingV2 {
108
+ bind(input: IngressTurnV2, principal: BookingIngressPrincipalV2): BookingIngressIdentityBindingV2 | Promise<BookingIngressIdentityBindingV2>
109
+ }
110
+ export interface BookingQuestionEventV2 {schemaVersion:typeof BOOKING_SURFACE_SCHEMA_VERSION_V2;eventId:string;taskId:string;contextRef:string;sequence:number;emittedAt:string;kind:'question';question:{questionId:string;prompt:string;missingFields:string[];type:'relaxation_approval_required';blocker:CriterionBlockerV2;approvalOptions:Array<{approval:RelaxationApprovalV2}>}}
111
+ export interface BookingEventBaseV2 { schemaVersion: typeof BOOKING_SURFACE_SCHEMA_VERSION_V2; eventId: string; taskId: string; contextRef: string; sequence: number; emittedAt: string }
112
+ export type BookingSurfaceEventV2 =
113
+ | (BookingEventBaseV2 & { kind: 'status'; status: 'submitted'|'working'|'waiting_receipt'|'input_required' })
114
+ | BookingQuestionEventV2
115
+ | (BookingEventBaseV2 & { kind: 'operation'; action: BookingReadActionV2 })
116
+ | (BookingEventBaseV2 & { kind: 'explanation'; explanation: { text: string; factRefs: string[] } })
117
+ | (BookingEventBaseV2 & { kind: 'terminal'; terminal: { status: 'completed'|'stopped'; summary: string; factRefs: string[] } })
118
+ | (BookingEventBaseV2 & { kind: 'error'; error: { code: string; message: string; retryable: boolean } })
@@ -0,0 +1,380 @@
1
+ /**
2
+ * Canonical TypeScript contract for HotelByte's embedded Booking Copilot.
3
+ *
4
+ * Executable facts cross this boundary only as discriminated data. Human text
5
+ * is limited to a user turn or an explanation and is never parsed as an action.
6
+ */
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
11
+ export const BOOKING_SURFACE_VERSION_HEADER = 'x-booking-surface-version' as const
12
+ export const BOOKING_SURFACE_SCHEMA_SHA256_HEADER = 'x-booking-surface-schema-sha256' as const
13
+
14
+ export const BOOKING_SURFACES = [
15
+ 'tenant',
16
+ 'customer_portal',
17
+ 'storefront',
18
+ 'payment_link',
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
71
+ value: T
72
+ }
73
+
74
+ export interface MoneyV1 {
75
+ /** Decimal string supplied by the authoritative page object; never recomputed by GoTry. */
76
+ amount: string
77
+ currency: string
78
+ sourceFactRef: FactRefV1
79
+ }
80
+
81
+ export interface OccupancyRoomV1 {
82
+ adults: number
83
+ childAges: number[]
84
+ }
85
+
86
+ export interface SearchCriteriaPatchV1 {
87
+ destination?: {
88
+ query?: string
89
+ placeRef?: string
90
+ }
91
+ hotel?: CriterionV1<{
92
+ name?: string
93
+ hotelRef?: HotelRefV1
94
+ }>
95
+ stay?: {
96
+ checkIn?: string
97
+ checkOut?: string
98
+ }
99
+ occupancy?: {
100
+ rooms: OccupancyRoomV1[]
101
+ }
102
+ budget?: CriterionV1<{
103
+ min?: MoneyV1
104
+ max?: MoneyV1
105
+ }>
106
+ starRating?: CriterionV1<{
107
+ min?: number
108
+ max?: number
109
+ }>
110
+ guestRating?: CriterionV1<{
111
+ min: number
112
+ }>
113
+ facilities?: CriterionV1<{
114
+ allOf: string[]
115
+ }>
116
+ distance?: CriterionV1<{
117
+ anchorLabel?: string
118
+ anchorRef?: string
119
+ maxKm: number
120
+ }>
121
+ }
122
+
123
+ export type ResultSortV1 =
124
+ | 'recommended'
125
+ | 'price_asc'
126
+ | 'price_desc'
127
+ | 'rating_desc'
128
+ | 'distance_asc'
129
+
130
+ export interface ResultsViewPatchV1 {
131
+ starRating?: { min?: number; max?: number } | null
132
+ guestRatingMin?: number | null
133
+ facilitiesAllOf?: string[] | null
134
+ distance?: { anchorRef: string; maxKm: number } | null
135
+ price?: { min?: MoneyV1; max?: MoneyV1 } | null
136
+ sort?: ResultSortV1
137
+ }
138
+
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>
149
+ targetCount?: number
150
+ sort?: 'best_match' | 'total_price_asc' | 'cancellation_latest'
151
+ }
152
+
153
+ export type EvidenceLevelV1 = 'listed' | 'rate_loaded' | 'checked'
154
+
155
+ export interface SurfaceCapabilitiesV1 {
156
+ surface: BookingSurfaceV1
157
+ allowedActions: BookingReadActionKindV1[]
158
+ }
159
+
160
+ export interface SearchDraftSnapshotV1 {
161
+ destination?: { query?: string; placeRef?: string }
162
+ stay?: { checkIn?: string; checkOut?: string }
163
+ occupancy?: { rooms: OccupancyRoomV1[] }
164
+ criteria?: SearchCriteriaPatchV1
165
+ }
166
+
167
+ export interface ResultViewSnapshotV1 {
168
+ status: 'idle' | 'loading' | 'ready' | 'partial' | 'failed'
169
+ filters?: ResultsViewPatchV1
170
+ sort?: ResultSortV1
171
+ resultCount?: number
172
+ searchSessionRef?: string
173
+ }
174
+
175
+ export interface VisibleHotelFactV1 {
176
+ hotelRef: HotelRefV1
177
+ name: string
178
+ starRating?: number
179
+ guestRating?: number
180
+ distanceKm?: number
181
+ facilityCodes?: string[]
182
+ factRefs: FactRefV1[]
183
+ }
184
+
185
+ export interface LoadedOfferFactV1 {
186
+ offerRef: OfferRefV1
187
+ hotelRef: HotelRefV1
188
+ evidenceLevel: EvidenceLevelV1
189
+ factRefs: FactRefV1[]
190
+ }
191
+
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
208
+ }
209
+
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
+ >
219
+
220
+ interface BookingReadActionBaseV1<K extends BookingReadActionKindV1, I> {
221
+ schemaVersion: typeof BOOKING_SURFACE_SCHEMA_VERSION
222
+ kind: K
223
+ actionId: string
224
+ contextRef: ContextRefV1
225
+ expectedRevision: number
226
+ reason: string
227
+ factRefs: FactRefV1[]
228
+ input: I
229
+ }
230
+
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 {
271
+ outcome: 'complete' | 'partial' | 'empty'
272
+ requestedCount?: number
273
+ actualCount?: number
274
+ hardCriteriaMet: boolean
275
+ factRefs: FactRefV1[]
276
+ gapCodes: string[]
277
+ }
278
+
279
+ export interface ActionReceiptV1 {
280
+ schemaVersion: typeof BOOKING_SURFACE_SCHEMA_VERSION
281
+ kind: 'action.receipt'
282
+ actionId: string
283
+ contextRef: ContextRefV1
284
+ status: ActionReceiptStatusV1
285
+ revision: number
286
+ observation: ActionObservationV1
287
+ resultContract: ResultContractV1
288
+ undoToken?: string
289
+ }
290
+
291
+ export interface UserTurnV1 {
292
+ schemaVersion: typeof BOOKING_SURFACE_SCHEMA_VERSION
293
+ 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
+ }
300
+ }
301
+
302
+ export interface BookingCopilotIngressTurnV1 {
303
+ schemaVersion: typeof BOOKING_SURFACE_SCHEMA_VERSION
304
+ 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
+ }
313
+ }
314
+
315
+ export interface ActionReceiptContinuationV1 {
316
+ schemaVersion: typeof BOOKING_SURFACE_SCHEMA_VERSION
317
+ kind: 'action.receipt.continuation'
318
+ taskId: string
319
+ workspace: BookingWorkspaceSnapshotV1
320
+ receipt: ActionReceiptV1
321
+ }
322
+
323
+ export type BookingCopilotTurnV1 = UserTurnV1 | ActionReceiptContinuationV1
324
+
325
+ interface BookingSurfaceEventBaseV1<K extends BookingSurfaceEventKindV1> {
326
+ schemaVersion: typeof BOOKING_SURFACE_SCHEMA_VERSION
327
+ eventId: string
328
+ taskId: string
329
+ contextRef: ContextRefV1
330
+ sequence: number
331
+ emittedAt: string
332
+ kind: K
333
+ }
334
+
335
+ export type BookingStatusEventV1 = BookingSurfaceEventBaseV1<'status'> & {
336
+ status: 'submitted' | 'working' | 'waiting_receipt' | 'input_required'
337
+ }
338
+
339
+ export type BookingQuestionEventV1 = BookingSurfaceEventBaseV1<'question'> & {
340
+ question: {
341
+ questionId: string
342
+ prompt: string
343
+ missingFields: string[]
344
+ }
345
+ }
346
+
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
+ }
372
+ }
373
+
374
+ export type BookingSurfaceEventV1 =
375
+ | BookingStatusEventV1
376
+ | BookingQuestionEventV1
377
+ | BookingOperationEventV1
378
+ | BookingExplanationEventV1
379
+ | BookingTerminalEventV1
380
+ | BookingErrorEventV1