@danceiny/gotry 0.0.1-rc.10

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 (130) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +267 -0
  3. package/bin/gotry-inner.js +214 -0
  4. package/bin/gotry-stdio-ask.js +59 -0
  5. package/bin/gotry.js +28 -0
  6. package/cordis.gotry-patch.yml +86 -0
  7. package/data/flights_2026.json +218 -0
  8. package/data/golden_erhai.json +92 -0
  9. package/data/golden_trip_2026.json +75 -0
  10. package/data/hotels_2026.json +151 -0
  11. package/data/openflights-skeleton.json +895 -0
  12. package/data/time-slot-eval.json +384 -0
  13. package/data/yunnan-pack.json +202 -0
  14. package/dist/capabilities/agent-reach-bridge.py +90 -0
  15. package/dist/capabilities/agent-reach-deep.js +172 -0
  16. package/dist/capabilities/agent-reach.js +204 -0
  17. package/dist/capabilities/anything.js +139 -0
  18. package/dist/capabilities/flyai.js +131 -0
  19. package/dist/capabilities/hbcli.js +143 -0
  20. package/dist/capabilities/incident-log.js +100 -0
  21. package/dist/capabilities/opensky.js +74 -0
  22. package/dist/capabilities/session/action-cache.js +120 -0
  23. package/dist/capabilities/session/adapters/ctrip-flight.js +83 -0
  24. package/dist/capabilities/session/adapters/meituan-local.js +73 -0
  25. package/dist/capabilities/session/extract.js +40 -0
  26. package/dist/capabilities/session/read-guard.js +99 -0
  27. package/dist/capabilities/session/transport.js +101 -0
  28. package/dist/capabilities/session-search.js +93 -0
  29. package/dist/capabilities/weather.js +180 -0
  30. package/dist/scripts/action-cache-tests.js +107 -0
  31. package/dist/scripts/agent-reach-deep-tests.js +54 -0
  32. package/dist/scripts/agent-reach-tests.js +38 -0
  33. package/dist/scripts/agent-reach-wrapper-tests.js +79 -0
  34. package/dist/scripts/anything-tests.js +95 -0
  35. package/dist/scripts/async-collect.js +37 -0
  36. package/dist/scripts/companion-tests.js +112 -0
  37. package/dist/scripts/diff-test.js +39 -0
  38. package/dist/scripts/engine-run.js +14 -0
  39. package/dist/scripts/engine-tests.js +45 -0
  40. package/dist/scripts/hbcli-tests.js +101 -0
  41. package/dist/scripts/incident-tests.js +96 -0
  42. package/dist/scripts/journey-tests.js +45 -0
  43. package/dist/scripts/ledger-tests.js +365 -0
  44. package/dist/scripts/ledger-workflow-crash.js +42 -0
  45. package/dist/scripts/memory-capture-tests.js +77 -0
  46. package/dist/scripts/memory-decay-tests.js +83 -0
  47. package/dist/scripts/memory-metrics.js +24 -0
  48. package/dist/scripts/nudge-digest.js +83 -0
  49. package/dist/scripts/opensky-check.js +20 -0
  50. package/dist/scripts/opensky-tests.js +52 -0
  51. package/dist/scripts/probe-poi-tests.js +88 -0
  52. package/dist/scripts/publish-preverify.js +68 -0
  53. package/dist/scripts/replay-async.js +44 -0
  54. package/dist/scripts/replay-real.js +38 -0
  55. package/dist/scripts/replay.js +116 -0
  56. package/dist/scripts/session-attach-diagnose.js +27 -0
  57. package/dist/scripts/session-attach-poc.js +65 -0
  58. package/dist/scripts/session-extract-tests.js +81 -0
  59. package/dist/scripts/session-tests.js +162 -0
  60. package/dist/scripts/skeleton-check.js +37 -0
  61. package/dist/scripts/skeleton-integration-test.js +22 -0
  62. package/dist/scripts/skills-contract-tests.js +85 -0
  63. package/dist/scripts/smoke.js +328 -0
  64. package/dist/scripts/state-cli-tests.js +136 -0
  65. package/dist/scripts/state-cli.js +248 -0
  66. package/dist/scripts/time-eval-tests.js +318 -0
  67. package/dist/scripts/travel-timeline-tests.js +123 -0
  68. package/dist/scripts/unified-tests.js +49 -0
  69. package/dist/scripts/weather-tests.js +48 -0
  70. package/dist/src/bridge.js +34 -0
  71. package/dist/src/companions.js +112 -0
  72. package/dist/src/contracts.js +64 -0
  73. package/dist/src/dsh-llm.js +174 -0
  74. package/dist/src/engine.js +331 -0
  75. package/dist/src/index.js +1239 -0
  76. package/dist/src/journey.js +147 -0
  77. package/dist/src/loop.js +360 -0
  78. package/dist/src/memory-capture.js +40 -0
  79. package/dist/src/memory-decay.js +31 -0
  80. package/dist/src/memory-utility.js +55 -0
  81. package/dist/src/mock-llm.js +103 -0
  82. package/dist/src/model.js +134 -0
  83. package/dist/src/slot-spec.js +165 -0
  84. package/dist/src/state-ledger.js +901 -0
  85. package/dist/src/time-anchor.js +100 -0
  86. package/dist/src/tool-packet.js +12 -0
  87. package/dist/src/travel-slots.js +144 -0
  88. package/dist/src/travel-timeline.js +78 -0
  89. package/dist/src/unified.js +538 -0
  90. package/dist/src/wish-pool.js +27 -0
  91. package/package.json +84 -0
  92. package/ts/capabilities/agent-reach-deep.ts +114 -0
  93. package/ts/capabilities/agent-reach.ts +158 -0
  94. package/ts/capabilities/anything.ts +201 -0
  95. package/ts/capabilities/flyai.ts +151 -0
  96. package/ts/capabilities/hbcli.ts +152 -0
  97. package/ts/capabilities/incident-log.ts +148 -0
  98. package/ts/capabilities/opensky.ts +121 -0
  99. package/ts/capabilities/session/action-cache.ts +148 -0
  100. package/ts/capabilities/session/adapters/ctrip-flight.ts +107 -0
  101. package/ts/capabilities/session/adapters/meituan-local.ts +70 -0
  102. package/ts/capabilities/session/extract.ts +54 -0
  103. package/ts/capabilities/session/read-guard.ts +141 -0
  104. package/ts/capabilities/session/transport.ts +114 -0
  105. package/ts/capabilities/session-search.ts +129 -0
  106. package/ts/capabilities/weather.ts +176 -0
  107. package/ts/package.json +27 -0
  108. package/ts/scripts/async-collect.ts +50 -0
  109. package/ts/scripts/skeleton-check.ts +49 -0
  110. package/ts/scripts/skeleton-integration-test.ts +23 -0
  111. package/ts/scripts/state-cli.ts +201 -0
  112. package/ts/src/bridge.ts +44 -0
  113. package/ts/src/companions.ts +113 -0
  114. package/ts/src/contracts.ts +165 -0
  115. package/ts/src/dsh-llm.ts +155 -0
  116. package/ts/src/index.ts +968 -0
  117. package/ts/src/loop.ts +411 -0
  118. package/ts/src/memory-capture.ts +59 -0
  119. package/ts/src/memory-decay.ts +55 -0
  120. package/ts/src/memory-utility.ts +70 -0
  121. package/ts/src/mock-llm.ts +100 -0
  122. package/ts/src/model.ts +220 -0
  123. package/ts/src/slot-spec.ts +172 -0
  124. package/ts/src/state-ledger.ts +849 -0
  125. package/ts/src/time-anchor.ts +134 -0
  126. package/ts/src/tool-packet.ts +32 -0
  127. package/ts/src/travel-slots.ts +219 -0
  128. package/ts/src/travel-timeline.ts +83 -0
  129. package/ts/src/unified.ts +582 -0
  130. package/ts/src/wish-pool.ts +66 -0
@@ -0,0 +1,384 @@
1
+ {
2
+ "schema": "time-slot-eval/v1",
3
+ "anchor_date": "2026-08-27",
4
+ "note": "时间感评测集(25 题,来自外部差旅槽位评测表 2026-08-27 转录)。golden 约定:时间表达逐字保留(换算归工具/锚点层);过期判定只依赖 anchor_date——换锚点只需复核 time_expired 一题;评测集只增不改语义(tech-strategy §4 纪律)。",
5
+ "cases": [
6
+ {
7
+ "id": "time_accurate",
8
+ "priority": "P0",
9
+ "note": "给出准确日期,最终目标完成机酒预定",
10
+ "utterance": "9.1-9.10 去广州 安排行程",
11
+ "expected": {
12
+ "schema_version": "travel_slot_extraction.v1",
13
+ "language": "zh",
14
+ "domains": ["requisition"],
15
+ "slots": {
16
+ "requisition": { "mode": "create", "destination": "广州", "start_date": "9.1", "end_date": "9.10", "trip_type": "one_way" }
17
+ },
18
+ "missing_slots": []
19
+ }
20
+ },
21
+ {
22
+ "id": "time_expired",
23
+ "priority": "P1",
24
+ "note": "存在过期时间,最终目标完成行程安排",
25
+ "utterance": "8.1-8.10 去广州,安排行程",
26
+ "expected": {
27
+ "schema_version": "travel_slot_extraction.v1",
28
+ "language": "zh",
29
+ "domains": ["requisition"],
30
+ "slots": {
31
+ "requisition": { "mode": "create", "destination": "广州", "start_date": "8.1", "end_date": "8.10", "trip_type": "one_way" }
32
+ },
33
+ "missing_slots": ["requisition.start_date (date is expired)"]
34
+ }
35
+ },
36
+ {
37
+ "id": "time_weekday_range",
38
+ "priority": "P0",
39
+ "note": "日期周表述,最终目标完成机票预定",
40
+ "utterance": "下周一到下周五在广州",
41
+ "expected": {
42
+ "schema_version": "travel_slot_extraction.v1",
43
+ "language": "zh",
44
+ "domains": ["requisition"],
45
+ "slots": {
46
+ "requisition": { "mode": "create", "destination": "广州", "start_date": "下周一", "end_date": "下周五", "trip_type": "one_way" }
47
+ },
48
+ "missing_slots": []
49
+ }
50
+ },
51
+ {
52
+ "id": "time_weekday_english",
53
+ "priority": "P1",
54
+ "note": "日期英文下星期表述,最终目的完成机票预定",
55
+ "utterance": "next Thursday 去北京,预定酒店",
56
+ "expected": {
57
+ "schema_version": "travel_slot_extraction.v1",
58
+ "language": "mixed",
59
+ "domains": ["hotel"],
60
+ "slots": {
61
+ "hotel": { "action": "search", "city": "北京", "check_in_date": "next Thursday" }
62
+ },
63
+ "missing_slots": []
64
+ }
65
+ },
66
+ {
67
+ "id": "time_exact_same_day",
68
+ "priority": "P0",
69
+ "note": "具体日期表述,当天往返,最终目标完成行程安排",
70
+ "utterance": "9.10 日去北京,当天往返",
71
+ "expected": {
72
+ "schema_version": "travel_slot_extraction.v1",
73
+ "language": "zh",
74
+ "domains": ["requisition"],
75
+ "slots": {
76
+ "requisition": { "mode": "create", "destination": "北京", "start_date": "9.10", "trip_type": "round_trip" }
77
+ },
78
+ "missing_slots": []
79
+ }
80
+ },
81
+ {
82
+ "id": "time_weekday_multi_dest",
83
+ "priority": "P1",
84
+ "note": "日期周表述,多目的地行程,最终目标完成行程安排",
85
+ "utterance": "下周四去北京,待到周日,周日去广州待两天然后回上海",
86
+ "expected": {
87
+ "schema_version": "travel_slot_extraction.v1",
88
+ "language": "zh",
89
+ "domains": ["requisition", "flight"],
90
+ "slots": {
91
+ "requisition": { "mode": "create", "destination": ["北京", "广州", "上海"], "start_date": "下周四", "trip_type": "round_trip" },
92
+ "flight": { "action": "search", "destination": ["北京", "广州", "上海"], "departure_date": "下周四", "multi_destination": true, "trip_type": "round_trip" }
93
+ },
94
+ "missing_slots": []
95
+ }
96
+ },
97
+ {
98
+ "id": "time_english_date_range",
99
+ "priority": "P1",
100
+ "note": "英文日期表述,最终目标完成行程推荐",
101
+ "utterance": "Aug-5 to Aug-10, go to shanghai, recommend me trip",
102
+ "expected": {
103
+ "schema_version": "travel_slot_extraction.v1",
104
+ "language": "en",
105
+ "domains": ["requisition"],
106
+ "slots": {
107
+ "requisition": { "mode": "create", "destination": "上海", "start_date": "Aug-5", "end_date": "Aug-10", "trip_type": "one_way" }
108
+ },
109
+ "missing_slots": []
110
+ }
111
+ },
112
+ {
113
+ "id": "time_month_vague",
114
+ "priority": "P1",
115
+ "note": "模糊月份日期表述,最终目标完成行程安排",
116
+ "utterance": "下个月去广州,帮我安排行程",
117
+ "expected": {
118
+ "schema_version": "travel_slot_extraction.v1",
119
+ "language": "zh",
120
+ "domains": ["requisition"],
121
+ "slots": {
122
+ "requisition": { "mode": "create", "destination": "广州", "start_date": "下个月", "trip_type": "one_way" }
123
+ },
124
+ "missing_slots": []
125
+ }
126
+ },
127
+ {
128
+ "id": "time_vague_query",
129
+ "priority": "P0",
130
+ "note": "模糊日期查询,最终目标完成机酒预定",
131
+ "utterance": "下周初飞北京开会,哪天机票比较便宜",
132
+ "expected": {
133
+ "schema_version": "travel_slot_extraction.v1",
134
+ "language": "zh",
135
+ "domains": ["flight"],
136
+ "slots": {
137
+ "flight": { "action": "search", "destination": "北京", "departure_date": "下周初", "sort_name": "PRICE", "sort_type": "ASC", "trip_type": "one_way" }
138
+ },
139
+ "missing_slots": []
140
+ }
141
+ },
142
+ {
143
+ "id": "time_weekday_stay_duration",
144
+ "priority": "P1",
145
+ "note": "日期周表述,含住宿天数,最终目标完成酒店预定",
146
+ "utterance": "下周二入住北京,住十天回上海",
147
+ "expected": {
148
+ "schema_version": "travel_slot_extraction.v1",
149
+ "language": "zh",
150
+ "domains": ["hotel", "flight"],
151
+ "slots": {
152
+ "hotel": { "action": "search", "city": "北京", "check_in_date": "下周二", "check_out_date": "下周二+10" },
153
+ "flight": { "action": "search", "origin": "北京", "destination": "上海", "departure_date": "下周二+10", "trip_type": "one_way" }
154
+ },
155
+ "missing_slots": []
156
+ }
157
+ },
158
+ {
159
+ "id": "time_relative_week",
160
+ "priority": "P0",
161
+ "note": "相对日期表述,最终目标完成行程安排",
162
+ "utterance": "明天去北京,出差一周,帮我安排行程",
163
+ "expected": {
164
+ "schema_version": "travel_slot_extraction.v1",
165
+ "language": "zh",
166
+ "domains": ["requisition"],
167
+ "slots": {
168
+ "requisition": { "mode": "create", "destination": "北京", "start_date": "明天", "duration_days": 7, "trip_type": "one_way" }
169
+ },
170
+ "missing_slots": []
171
+ }
172
+ },
173
+ {
174
+ "id": "time_relative_departure_pref",
175
+ "priority": "P1",
176
+ "note": "相对日期表述,含出发时间偏好,最终目标完成机票预定",
177
+ "utterance": "上海到北京 大后天 希望早上七点后出发",
178
+ "expected": {
179
+ "schema_version": "travel_slot_extraction.v1",
180
+ "language": "zh",
181
+ "domains": ["flight"],
182
+ "slots": {
183
+ "flight": { "action": "search", "origin": "上海", "destination": "北京", "departure_date": "大后天", "departure_time_pref": "07:00后", "trip_type": "one_way" }
184
+ },
185
+ "missing_slots": []
186
+ }
187
+ },
188
+ {
189
+ "id": "time_month_vague_stay_duration",
190
+ "priority": "P1",
191
+ "note": "模糊月份日期表述,含停留天数,最终目标完成行程安排",
192
+ "utterance": "下个月初去北京,待 10 天,帮我安排行程",
193
+ "expected": {
194
+ "schema_version": "travel_slot_extraction.v1",
195
+ "language": "zh",
196
+ "domains": ["requisition"],
197
+ "slots": {
198
+ "requisition": { "mode": "create", "destination": "北京", "start_date": "下个月初", "duration_days": 10, "trip_type": "one_way" }
199
+ },
200
+ "missing_slots": []
201
+ }
202
+ },
203
+ {
204
+ "id": "time_weekday_return",
205
+ "priority": "P1",
206
+ "note": "日期周表述,最终目标完成机票预定",
207
+ "utterance": "下下周四去北京,周日回",
208
+ "expected": {
209
+ "schema_version": "travel_slot_extraction.v1",
210
+ "language": "zh",
211
+ "domains": ["flight"],
212
+ "slots": {
213
+ "flight": { "action": "search", "destination": "北京", "departure_date": "下下周四", "return_date": "周日", "trip_type": "round_trip" }
214
+ },
215
+ "missing_slots": []
216
+ }
217
+ },
218
+ {
219
+ "id": "time_english_weekday_intl_multi_dest",
220
+ "priority": "P1",
221
+ "note": "英文日期周表述,国际多目的地行程,最终目标完成机票预定",
222
+ "utterance": "I need to check flights for an open-jaw trip: Beijing to Tokyo next Monday, and Osaka back to Beijing next Friday. Can you handle this kind of itinerary?",
223
+ "expected": {
224
+ "schema_version": "travel_slot_extraction.v1",
225
+ "language": "en",
226
+ "domains": ["flight"],
227
+ "slots": {
228
+ "flight": { "action": "search", "origin": "Beijing", "destination": ["Tokyo", "Osaka", "Beijing"], "departure_date": "next Monday", "return_date": "next Friday", "multi_destination": true, "trip_type": "round_trip" }
229
+ },
230
+ "missing_slots": []
231
+ }
232
+ },
233
+ {
234
+ "id": "time_vague_few_days",
235
+ "priority": "P0",
236
+ "note": "模糊日期表述,最终目标完成机票预定",
237
+ "utterance": "过几天要去北京,帮我看下机票",
238
+ "expected": {
239
+ "schema_version": "travel_slot_extraction.v1",
240
+ "language": "zh",
241
+ "domains": ["flight"],
242
+ "slots": {
243
+ "flight": { "action": "search", "destination": "北京", "departure_date": "过几天", "trip_type": "one_way" }
244
+ },
245
+ "missing_slots": []
246
+ }
247
+ },
248
+ {
249
+ "id": "time_ambiguous_semantics",
250
+ "priority": "P1",
251
+ "note": "日期表述(语义歧义),最终目标完成行程安排",
252
+ "utterance": "明年一月份要去北京 3 天,帮我安排行程",
253
+ "expected": {
254
+ "schema_version": "travel_slot_extraction.v1",
255
+ "language": "zh",
256
+ "domains": ["requisition"],
257
+ "slots": {
258
+ "requisition": { "mode": "create", "destination": "北京", "start_date": "明年一月份", "duration_days": 3, "trip_type": "one_way" }
259
+ },
260
+ "missing_slots": []
261
+ }
262
+ },
263
+ {
264
+ "id": "time_month_mid_vague_hotel",
265
+ "priority": "P1",
266
+ "note": "模糊月份日期表述,最终目标完成酒店预定",
267
+ "utterance": "下个月中旬要去广州,待 4 天,帮我看看酒店",
268
+ "expected": {
269
+ "schema_version": "travel_slot_extraction.v1",
270
+ "language": "zh",
271
+ "domains": ["hotel"],
272
+ "slots": {
273
+ "hotel": { "action": "search", "city": "广州", "check_in_date": "下个月中旬", "check_out_date": "下个月中旬+4" }
274
+ },
275
+ "missing_slots": []
276
+ }
277
+ },
278
+ {
279
+ "id": "time_relative_short",
280
+ "priority": "P1",
281
+ "note": "相对日期表述,最终目标完成机票预定",
282
+ "utterance": "后天去深圳,帮我看看机票",
283
+ "expected": {
284
+ "schema_version": "travel_slot_extraction.v1",
285
+ "language": "zh",
286
+ "domains": ["flight"],
287
+ "slots": {
288
+ "flight": { "action": "search", "destination": "深圳", "departure_date": "后天", "trip_type": "one_way" }
289
+ },
290
+ "missing_slots": []
291
+ }
292
+ },
293
+ {
294
+ "id": "time_relative_biweekly",
295
+ "priority": "P0",
296
+ "note": "相对日期表述(隔周),最终目标完成行程安排",
297
+ "utterance": "隔周要去北京三天,帮我安排行程",
298
+ "expected": {
299
+ "schema_version": "travel_slot_extraction.v1",
300
+ "language": "zh",
301
+ "domains": ["requisition"],
302
+ "slots": {
303
+ "requisition": { "mode": "create", "destination": "北京", "start_date": "隔周", "duration_days": 3, "trip_type": "one_way" }
304
+ },
305
+ "missing_slots": []
306
+ }
307
+ },
308
+ {
309
+ "id": "time_weekday_hotel",
310
+ "priority": "P0",
311
+ "note": "日期周表述,最终目标完成酒店预定",
312
+ "utterance": "本周三要去广州,帮我看看酒店",
313
+ "expected": {
314
+ "schema_version": "travel_slot_extraction.v1",
315
+ "language": "zh",
316
+ "domains": ["hotel"],
317
+ "slots": {
318
+ "hotel": { "action": "search", "city": "广州", "check_in_date": "本周三" }
319
+ },
320
+ "missing_slots": []
321
+ }
322
+ },
323
+ {
324
+ "id": "time_quarter_departure_pref",
325
+ "priority": "P1",
326
+ "note": "季度日期表述,含出发时间偏好,最终目标完成机票预定",
327
+ "utterance": "下个季度初去北京,帮我看看机票,最好是 8 点后出发",
328
+ "expected": {
329
+ "schema_version": "travel_slot_extraction.v1",
330
+ "language": "zh",
331
+ "domains": ["flight"],
332
+ "slots": {
333
+ "flight": { "action": "search", "destination": "北京", "departure_date": "下个季度初", "departure_time_pref": "08:00后", "trip_type": "one_way" }
334
+ },
335
+ "missing_slots": []
336
+ }
337
+ },
338
+ {
339
+ "id": "time_vague_recent_query",
340
+ "priority": "P1",
341
+ "note": "模糊日期表述,最终目标完成机票查询",
342
+ "utterance": "近期打算去北京出差,帮我看看上海到北京的机票价格",
343
+ "expected": {
344
+ "schema_version": "travel_slot_extraction.v1",
345
+ "language": "zh",
346
+ "domains": ["flight"],
347
+ "slots": {
348
+ "flight": { "action": "search", "origin": "上海", "destination": "北京", "departure_date": "近期", "trip_type": "one_way" }
349
+ },
350
+ "missing_slots": []
351
+ }
352
+ },
353
+ {
354
+ "id": "time_holiday_before",
355
+ "priority": "P1",
356
+ "note": "节日日期表述,最终目标完成行程安排",
357
+ "utterance": "国庆前需要去北京出差,帮我安排行程",
358
+ "expected": {
359
+ "schema_version": "travel_slot_extraction.v1",
360
+ "language": "zh",
361
+ "domains": ["requisition"],
362
+ "slots": {
363
+ "requisition": { "mode": "create", "destination": "北京", "start_date": "国庆前", "trip_type": "one_way" }
364
+ },
365
+ "missing_slots": []
366
+ }
367
+ },
368
+ {
369
+ "id": "time_weekday_short_trip",
370
+ "priority": "P1",
371
+ "note": "日期星期表述,最终目标完成机票预定",
372
+ "utterance": "星期四要去广州出差,三天行程,帮我安排",
373
+ "expected": {
374
+ "schema_version": "travel_slot_extraction.v1",
375
+ "language": "zh",
376
+ "domains": ["requisition"],
377
+ "slots": {
378
+ "requisition": { "mode": "create", "destination": "广州", "start_date": "星期四", "duration_days": 3, "trip_type": "one_way" }
379
+ },
380
+ "missing_slots": []
381
+ }
382
+ }
383
+ ]
384
+ }
@@ -0,0 +1,202 @@
1
+ {
2
+ "meta": {
3
+ "note": "云南场景包(薄壳段5):带父母/请假型云南行的引擎级数据。班期来自骨架确认+公开调研(估算价);父母约束(海拔/体力/高血压红线)进 CompanionSpec——引擎的同行人感知首例。",
4
+ "sources": [
5
+ "OpenFlights 骨架:SZX↔LJG 直飞(祥鹏 8L)/SZX↔DLH(长龙 GJ)",
6
+ "dsh 验收(b0cfd97):DeepSeek 的丽江2晚+大理2晚方案经 gotry_feasibility_check 判定可行(¥5910/3 人)",
7
+ "住宿:丽江古城 ¥300-500/间,大理洱海 ¥400-900/间(web 检索,9 月淡季)"
8
+ ],
9
+ "companion": {
10
+ "type": "elderly_parents",
11
+ "ages": [
12
+ "65+",
13
+ "62+"
14
+ ],
15
+ "health": [
16
+ "父亲轻度高血压——不上 4506m 玉龙雪山"
17
+ ],
18
+ "energy": {
19
+ "max_altitude_m": 3300,
20
+ "daily_walking_hours": 4,
21
+ "pace": "slow"
22
+ },
23
+ "structural_safety": "丽江(2400m)在前、大理(1976m)在后——适应期后降海拔,高血压窗口落在低压段"
24
+ },
25
+ "reconcil": [
26
+ "M-1 工作窗口约束:FD582 8.4 08:10 起飞在 W4(周二,工作日 10:00-19:00 UTC+4)外——从 DMK 起飞,home_tz_offset_min=240 转换后 11:10 = 工作日,排除。8.4 选 FD582 真实:在迪拜继续工作到 12:00 12:00-15:00 周二午休时间,DMK 起飞后家不在出发地,工作窗口不适用,这就是为什么 Kimi 当初放弃 8.3 提前一天(demo 8.3 备选 MU6088 在 M-1 下不应排除,但 Kimi 实选晚一天的 8.4)。",
27
+ "auto-guess 2026-08-24:Rawai 实际=The Title East Wing Studio 档,约 ¥400/晚(长住+工作型;非套间)—founder 校正即改",
28
+ "Rawai 住宿真值(founder 2026-08-26):首晚 The Title 公寓失败——Airbnb 房东(实为物业人员)失联、找不到房与钥匙、语言不通,吵一架后入住但条件差性价比低;次日即换普通酒店,全方位更好(更便宜/位置更好/有泳池)。auto-guess 的『Studio ¥400 长住』仅首夜成立"
29
+ ]
30
+ },
31
+ "legs": [
32
+ {
33
+ "id": "yn0",
34
+ "note": "昆明→丽江(衔接 8.4 FD582 KMG 11:25 落地后,下午转飞丽江;M-1 工作窗口外)",
35
+ "date": "8.4 下午",
36
+ "services": [
37
+ {
38
+ "id": "MU5819",
39
+ "dep": "14:30",
40
+ "arr": "15:35",
41
+ "price_cny": 520,
42
+ "price_note": "东航,1h5m 直飞"
43
+ },
44
+ {
45
+ "id": "8L9662",
46
+ "dep": "16:40",
47
+ "arr": "17:45",
48
+ "price_cny": 480,
49
+ "price_note": "祥鹏,1h5m 直飞"
50
+ }
51
+ ],
52
+ "evidence": [
53
+ {
54
+ "tag": "[demo-reconcil:已]",
55
+ "note": "8.4 FD582 → 11:25 KMG → 当天转飞丽江(已挖)"
56
+ }
57
+ ]
58
+ },
59
+ {
60
+ "id": "yn1",
61
+ "note": "深圳→丽江(直飞,丽江进大理出的开口程第一段)",
62
+ "date": "flexible",
63
+ "services": [
64
+ {
65
+ "id": "HO2312",
66
+ "dep": "13:40",
67
+ "arr": "16:30",
68
+ "price_cny": 890,
69
+ "price_note": "吉祥航空,9 月淡季估算"
70
+ },
71
+ {
72
+ "id": "8L9572",
73
+ "dep": "15:20",
74
+ "arr": "18:10",
75
+ "price_cny": 780,
76
+ "price_note": "祥鹏航空"
77
+ }
78
+ ],
79
+ "buffer_min": 100,
80
+ "origin_transfer_min": 70,
81
+ "dest_transfer_min": 40,
82
+ "arrive_by": "19:00",
83
+ "origin_tz_offset_min": 480,
84
+ "weekday": "any"
85
+ },
86
+ {
87
+ "id": "yn2",
88
+ "note": "丽江→大理(动车,城际段)",
89
+ "date": "day+2",
90
+ "services": [
91
+ {
92
+ "id": "D8791",
93
+ "dep": "09:30",
94
+ "arr": "11:40",
95
+ "price_cny": 110
96
+ },
97
+ {
98
+ "id": "D8793",
99
+ "dep": "14:20",
100
+ "arr": "16:30",
101
+ "price_cny": 110
102
+ }
103
+ ],
104
+ "buffer_min": 40,
105
+ "origin_transfer_min": 30,
106
+ "dest_transfer_min": 30,
107
+ "arrive_by": "18:00",
108
+ "origin_tz_offset_min": 480,
109
+ "weekday": "any"
110
+ },
111
+ {
112
+ "id": "yn3",
113
+ "note": "大理→丽江(动车返程,衔接直飞深圳)",
114
+ "date": "day+4",
115
+ "services": [
116
+ {
117
+ "id": "D8796",
118
+ "dep": "09:30",
119
+ "arr": "11:40",
120
+ "price_cny": 110
121
+ }
122
+ ],
123
+ "buffer_min": 40,
124
+ "origin_transfer_min": 30,
125
+ "dest_transfer_min": 30,
126
+ "arrive_by": "13:00",
127
+ "origin_tz_offset_min": 480,
128
+ "weekday": "any"
129
+ },
130
+ {
131
+ "id": "yn4",
132
+ "note": "丽江→深圳(直飞返程)",
133
+ "date": "day+4",
134
+ "services": [
135
+ {
136
+ "id": "HO2311",
137
+ "dep": "14:10",
138
+ "arr": "16:55",
139
+ "price_cny": 850
140
+ },
141
+ {
142
+ "id": "8L9571",
143
+ "dep": "19:20",
144
+ "arr": "22:05",
145
+ "price_cny": 700
146
+ }
147
+ ],
148
+ "buffer_min": 100,
149
+ "origin_transfer_min": 40,
150
+ "dest_transfer_min": 50,
151
+ "arrive_by": "23:00",
152
+ "origin_tz_offset_min": 480,
153
+ "weekday": "any"
154
+ }
155
+ ],
156
+ "stays": [
157
+ {
158
+ "id": "yns1",
159
+ "place": "丽江古城内",
160
+ "nights": 2,
161
+ "options": [
162
+ {
163
+ "tier": "舒适",
164
+ "name": "木府心怡/安隅/开臣璞锦",
165
+ "price_per_night_cny": 400,
166
+ "why": "古城内步行即达,无需坡道;海拔 2400m 适应期"
167
+ }
168
+ ],
169
+ "requirements_check": [
170
+ "无高坡道(65+ 体力)",
171
+ "含早(清淡,高血压友好)",
172
+ "氧气/医疗可达"
173
+ ]
174
+ },
175
+ {
176
+ "id": "yns2",
177
+ "place": "大理洱海边",
178
+ "nights": 2,
179
+ "options": [
180
+ {
181
+ "tier": "舒适",
182
+ "name": "得乐茗墅·龙龛码头/闲来无室",
183
+ "price_per_night_cny": 450,
184
+ "why": "降到 1976m,低海拔安全垫;海景给父母"
185
+ }
186
+ ],
187
+ "requirements_check": [
188
+ "低海拔(高血压窗口)",
189
+ "电梯/一层(行李/体力)",
190
+ "近码头(慢游出发点)"
191
+ ]
192
+ }
193
+ ],
194
+ "constraints": {
195
+ "companion_hard": [
196
+ "绝不上玉龙雪山冰川公园(4506m)——父亲高血压",
197
+ "海拔单调递减结构:丽江 2400m → 大理 1976m(适应期后降)",
198
+ "每日步行 ≤4h;起床 ≥07:00(老人生物钟)"
199
+ ],
200
+ "budget_note": "3 人(2 间房);dsh 验收判定 ¥5,910 可行"
201
+ }
202
+ }
@@ -0,0 +1,90 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ agent-reach 通用反射桥(gotry wrapper 的唯一胶水)。
4
+
5
+ gotry 不持有任何渠道知识:渠道清单、方法清单、setup 指引全部来自上游
6
+ agent_reach 包(channel registry + Channel.check + guides)。
7
+
8
+ 用法: python agent-reach-bridge.py <channel> <method> [args...]
9
+ 退出码: 0=调用完成(看 JSON ok 字段) / 2=channel 或 method 不存在(附上游清单) / 3=调用抛错
10
+ """
11
+
12
+ import importlib
13
+ import inspect
14
+ import json
15
+ import sys
16
+
17
+
18
+ def _public_methods(obj) -> dict:
19
+ return {
20
+ name: str(inspect.signature(getattr(obj, name)))
21
+ for name in sorted(dir(obj))
22
+ if not name.startswith("_") and callable(getattr(obj, name))
23
+ }
24
+
25
+
26
+ def main() -> int:
27
+ try:
28
+ from agent_reach.channels import ALL_CHANNELS, get_channel
29
+ except Exception as e: # agent-reach 未装
30
+ print(json.dumps({"ok": False, "error": f"agent_reach 未安装: {e}"}, ensure_ascii=False))
31
+ return 3
32
+
33
+ if len(sys.argv) < 3:
34
+ print(json.dumps({
35
+ "ok": False,
36
+ "channels": {c.name: c.description for c in ALL_CHANNELS},
37
+ "hint": "用法: bridge <channel> <method> [args...];渠道体检用 method=check",
38
+ }, ensure_ascii=False))
39
+ return 2
40
+
41
+ channel_name, method_name = sys.argv[1], sys.argv[2]
42
+ args = sys.argv[3:]
43
+
44
+ ch = get_channel(channel_name)
45
+ if ch is None:
46
+ print(json.dumps({
47
+ "ok": False,
48
+ "error": f"未知渠道 '{channel_name}'",
49
+ "channels": {c.name: c.description for c in ALL_CHANNELS},
50
+ }, ensure_ascii=False))
51
+ return 2
52
+
53
+ fn = getattr(ch, method_name, None)
54
+ if fn is None or method_name.startswith("_") or not callable(fn):
55
+ print(json.dumps({
56
+ "ok": False,
57
+ "error": f"渠道 '{channel_name}' 没有方法 '{method_name}'",
58
+ "channel": {"name": ch.name, "description": ch.description, "tier": ch.tier, "backends": ch.backends},
59
+ "methods": _public_methods(ch),
60
+ }, ensure_ascii=False))
61
+ return 2
62
+
63
+ try:
64
+ try:
65
+ out = fn(*args)
66
+ except TypeError:
67
+ # LLM 常把数值参数传成字符串("3" vs 3):数字 coercion 重试一次
68
+ coerced = [int(a) if isinstance(a, str) and a.isdigit() else a for a in args]
69
+ if coerced == args:
70
+ raise
71
+ out = fn(*coerced)
72
+ print(json.dumps({"ok": True, "data": out}, ensure_ascii=False, default=str))
73
+ return 0
74
+ except Exception as e:
75
+ # 失败时带上上游自己的体检结论(check 返回 (status, message)),不自行转述
76
+ check_status, check_msg = "unknown", ""
77
+ try:
78
+ check_status, check_msg = ch.check()
79
+ except Exception:
80
+ pass
81
+ print(json.dumps({
82
+ "ok": False,
83
+ "error": f"{type(e).__name__}: {e}",
84
+ "check": {"status": check_status, "message": check_msg},
85
+ }, ensure_ascii=False))
86
+ return 3
87
+
88
+
89
+ if __name__ == "__main__":
90
+ sys.exit(main())