@danceiny/gotry 0.0.1-rc.17 → 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 +185 -148
  2. package/README.zh-CN.md +195 -154
  3. package/bin/gotry-bootstrap.js +246 -26
  4. package/bin/gotry-inner.js +68 -38
  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 +115 -44
  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
@@ -314,6 +314,30 @@ for (const invalid of [
314
314
  '<done>{"ok":</done>'
315
315
  ])assert.equal(parseBenchmarkTerminal(invalid, projection.terminal).ok, false);
316
316
  assert.equal(parseBenchmarkTerminal(`<done>{"x":"${'y'.repeat(1024)}"}</done>`, projection.terminal).ok, false);
317
+ for (const [raw, expectOk] of [
318
+ [
319
+ '<think>plan it</think><done>{"ok":true}</done>',
320
+ true
321
+ ],
322
+ [
323
+ '<think>a</think>\n<THINK>b</THINK>\n<done>{"ok":true}</done>',
324
+ true
325
+ ],
326
+ [
327
+ '<done>{"ok":true}</done><think>after</think>',
328
+ true
329
+ ],
330
+ [
331
+ '<think>unclosed<done>{"ok":true}</done>',
332
+ false
333
+ ],
334
+ [
335
+ 'prose<think>x</think><done>{"ok":true}</done>',
336
+ false
337
+ ]
338
+ ]){
339
+ assert.equal(parseBenchmarkTerminal(raw, projection.terminal).ok, expectOk, raw);
340
+ }
317
341
  function turnStart(turn = 1) {
318
342
  return {
319
343
  type: 'turn/start',
@@ -343,11 +367,9 @@ function toolCall(callId = 'call-1', options = {}) {
343
367
  callId,
344
368
  name: projection.toolName,
345
369
  arguments: JSON.stringify({
346
- query: {
347
- action,
348
- tool,
349
- arguments: {}
350
- }
370
+ action,
371
+ tool,
372
+ arguments: {}
351
373
  })
352
374
  }
353
375
  };
@@ -1608,11 +1630,9 @@ try {
1608
1630
  payload: '$(touch /tmp/nope)'
1609
1631
  };
1610
1632
  const result = await bridge.execute({
1611
- query: {
1612
- action: 'call',
1613
- tool: 'lookup',
1614
- arguments: args
1615
- }
1633
+ action: 'call',
1634
+ tool: 'lookup',
1635
+ arguments: args
1616
1636
  }, null);
1617
1637
  assert.deepEqual(spawnSpecs[0]?.argv, [
1618
1638
  process.execPath,
@@ -1653,12 +1673,10 @@ try {
1653
1673
  stdout: '{"result":{"city":"Dubai"}}'
1654
1674
  });
1655
1675
  const unmappedResult = await bridge.execute({
1656
- query: {
1657
- action: 'call',
1658
- tool: 'toString',
1659
- arguments: {
1660
- city: 'Dubai'
1661
- }
1676
+ action: 'call',
1677
+ tool: 'toString',
1678
+ arguments: {
1679
+ city: 'Dubai'
1662
1680
  }
1663
1681
  }, null);
1664
1682
  assert.deepEqual(unmappedResult, {
@@ -1671,12 +1689,10 @@ try {
1671
1689
  stdout: '{"result":{"legacy":"value"}}'
1672
1690
  });
1673
1691
  const legacyResult = await bridge.execute({
1674
- query: {
1675
- action: 'call',
1676
- tool: 'constructor',
1677
- arguments: {
1678
- city: 'Dubai'
1679
- }
1692
+ action: 'call',
1693
+ tool: 'constructor',
1694
+ arguments: {
1695
+ city: 'Dubai'
1680
1696
  }
1681
1697
  }, null);
1682
1698
  assert.deepEqual(legacyResult, {
@@ -1689,12 +1705,10 @@ try {
1689
1705
  stdout: '{"result":{"city":"Dubai"}}'
1690
1706
  });
1691
1707
  const constructorUnexpected = await bridge.execute({
1692
- query: {
1693
- action: 'call',
1694
- tool: 'constructor',
1695
- arguments: {
1696
- city: 'Dubai'
1697
- }
1708
+ action: 'call',
1709
+ tool: 'constructor',
1710
+ arguments: {
1711
+ city: 'Dubai'
1698
1712
  }
1699
1713
  }, null);
1700
1714
  assert.deepEqual(constructorUnexpected, {
@@ -1705,12 +1719,10 @@ try {
1705
1719
  stdout: '{"result":{"nested":{"city":"Dubai"}}}'
1706
1720
  });
1707
1721
  const nestedAllowedResult = await bridge.execute({
1708
- query: {
1709
- action: 'call',
1710
- tool: 'lookup',
1711
- arguments: {
1712
- city: 'Dubai'
1713
- }
1722
+ action: 'call',
1723
+ tool: 'lookup',
1724
+ arguments: {
1725
+ city: 'Dubai'
1714
1726
  }
1715
1727
  }, null);
1716
1728
  assert.deepEqual(nestedAllowedResult, {
@@ -1725,12 +1737,10 @@ try {
1725
1737
  stdout: '{"result":{"city":"Dubai","unexpected":"secret"}}'
1726
1738
  });
1727
1739
  const unexpectedResult = await bridge.execute({
1728
- query: {
1729
- action: 'call',
1730
- tool: 'lookup',
1731
- arguments: {
1732
- city: 'Dubai'
1733
- }
1740
+ action: 'call',
1741
+ tool: 'lookup',
1742
+ arguments: {
1743
+ city: 'Dubai'
1734
1744
  }
1735
1745
  }, null);
1736
1746
  assert.deepEqual(unexpectedResult, {
@@ -1741,12 +1751,10 @@ try {
1741
1751
  stdout: '{"result":[{"city":"Dubai","nested":{"unexpected":"secret"}}]}'
1742
1752
  });
1743
1753
  const nestedUnexpectedResult = await bridge.execute({
1744
- query: {
1745
- action: 'call',
1746
- tool: 'lookup',
1747
- arguments: {
1748
- city: 'Dubai'
1749
- }
1754
+ action: 'call',
1755
+ tool: 'lookup',
1756
+ arguments: {
1757
+ city: 'Dubai'
1750
1758
  }
1751
1759
  }, null);
1752
1760
  assert.deepEqual(nestedUnexpectedResult, {
@@ -1782,12 +1790,10 @@ try {
1782
1790
  })
1783
1791
  });
1784
1792
  const forbiddenResult = await bridge.execute({
1785
- query: {
1786
- action: 'call',
1787
- tool: 'lookup',
1788
- arguments: {
1789
- city: 'Dubai'
1790
- }
1793
+ action: 'call',
1794
+ tool: 'lookup',
1795
+ arguments: {
1796
+ city: 'Dubai'
1791
1797
  }
1792
1798
  }, null);
1793
1799
  assert.deepEqual(forbiddenResult, {
@@ -1799,12 +1805,10 @@ try {
1799
1805
  stdout: '{"result":"the hidden answer"}'
1800
1806
  });
1801
1807
  const primitiveOutput = await bridge.execute({
1802
- query: {
1803
- action: 'call',
1804
- tool: 'lookup',
1805
- arguments: {
1806
- city: 'Dubai'
1807
- }
1808
+ action: 'call',
1809
+ tool: 'lookup',
1810
+ arguments: {
1811
+ city: 'Dubai'
1808
1812
  }
1809
1813
  }, null);
1810
1814
  assert.deepEqual(primitiveOutput, {
@@ -1813,12 +1817,10 @@ try {
1813
1817
  }, 'primitive result strings cannot bypass the structured visible-output boundary');
1814
1818
  const beforeOversized = spawnSpecs.length;
1815
1819
  const oversized = await bridge.execute({
1816
- query: {
1817
- action: 'call',
1818
- tool: 'lookup',
1819
- arguments: {
1820
- blob: 'x'.repeat(65_537)
1821
- }
1820
+ action: 'call',
1821
+ tool: 'lookup',
1822
+ arguments: {
1823
+ blob: 'x'.repeat(65_537)
1822
1824
  }
1823
1825
  }, null);
1824
1826
  assert.deepEqual(oversized, {
@@ -1833,11 +1835,9 @@ try {
1833
1835
  next: deep
1834
1836
  };
1835
1837
  const deepResult = await bridge.execute({
1836
- query: {
1837
- action: 'call',
1838
- tool: 'lookup',
1839
- arguments: deep
1840
- }
1838
+ action: 'call',
1839
+ tool: 'lookup',
1840
+ arguments: deep
1841
1841
  }, null);
1842
1842
  assert.deepEqual(deepResult, {
1843
1843
  ok: false,
@@ -1847,17 +1847,15 @@ try {
1847
1847
  assert.equal(spawnSpecs.length, beforeDeep, 'over-deep arguments are rejected before spawn');
1848
1848
  const beforeOverride = spawnSpecs.length;
1849
1849
  const overrideResult = await bridge.execute({
1850
- query: {
1851
- action: 'call',
1852
- tool: 'lookup',
1853
- arguments: {
1854
- city: 'Dubai',
1855
- executable: '/tmp/evil',
1856
- cwd: '/tmp/evil',
1857
- argv: [
1858
- '--unsafe'
1859
- ]
1860
- }
1850
+ action: 'call',
1851
+ tool: 'lookup',
1852
+ arguments: {
1853
+ city: 'Dubai',
1854
+ executable: '/tmp/evil',
1855
+ cwd: '/tmp/evil',
1856
+ argv: [
1857
+ '--unsafe'
1858
+ ]
1861
1859
  }
1862
1860
  }, null);
1863
1861
  assert.deepEqual(spawnSpecs[beforeOverride]?.argv, [
@@ -1883,12 +1881,10 @@ try {
1883
1881
  lossy: true
1884
1882
  });
1885
1883
  const truncated = await bridge.execute({
1886
- query: {
1887
- action: 'call',
1888
- tool: 'lookup',
1889
- arguments: {
1890
- city: 'Dubai'
1891
- }
1884
+ action: 'call',
1885
+ tool: 'lookup',
1886
+ arguments: {
1887
+ city: 'Dubai'
1892
1888
  }
1893
1889
  }, null);
1894
1890
  assert.deepEqual(truncated, {
@@ -1902,12 +1898,10 @@ try {
1902
1898
  signal: 'SIGTERM'
1903
1899
  });
1904
1900
  const failed = await bridge.execute({
1905
- query: {
1906
- action: 'call',
1907
- tool: 'lookup',
1908
- arguments: {
1909
- city: 'Dubai'
1910
- }
1901
+ action: 'call',
1902
+ tool: 'lookup',
1903
+ arguments: {
1904
+ city: 'Dubai'
1911
1905
  }
1912
1906
  }, null);
1913
1907
  assert.deepEqual(failed, {
@@ -1916,6 +1910,27 @@ try {
1916
1910
  exit_code: 17,
1917
1911
  signal: 'SIGTERM'
1918
1912
  }, 'nonzero runner result is structured without stderr echo');
1913
+ const errorsTable = await bridge.execute({
1914
+ action: 'errors'
1915
+ }, null);
1916
+ assert.ok(errorsTable.ok === true && errorsTable.errors, 'errors 契约表可拉取');
1917
+ for (const code of [
1918
+ 'invalid_action',
1919
+ 'disallowed_tool',
1920
+ 'invalid_arguments',
1921
+ 'timed_out',
1922
+ 'output_truncated',
1923
+ 'invalid_json',
1924
+ 'invalid_output',
1925
+ 'runner_failed',
1926
+ 'spawn_failed',
1927
+ 'forbidden_output'
1928
+ ]){
1929
+ const row = errorsTable.errors?.[code];
1930
+ assert.ok(row && typeof row.recoverable === 'boolean' && row.remedy.length > 0, `契约表应含 ${code}(recoverable+remedy)`);
1931
+ }
1932
+ assert.equal(errorsTable.errors?.invalid_arguments?.recoverable, true, '参数形态错=调用方可恢复');
1933
+ assert.equal(errorsTable.errors?.forbidden_output?.recoverable, false, '策略边界=不可恢复');
1919
1934
  for (const stdout of [
1920
1935
  'not-json',
1921
1936
  '{"result":1}{"result":2}'
@@ -1924,12 +1939,10 @@ try {
1924
1939
  stdout
1925
1940
  });
1926
1941
  const malformed = await bridge.execute({
1927
- query: {
1928
- action: 'call',
1929
- tool: 'lookup',
1930
- arguments: {
1931
- city: 'Dubai'
1932
- }
1942
+ action: 'call',
1943
+ tool: 'lookup',
1944
+ arguments: {
1945
+ city: 'Dubai'
1933
1946
  }
1934
1947
  }, null);
1935
1948
  assert.deepEqual(malformed, {
@@ -1941,12 +1954,10 @@ try {
1941
1954
  spawnError: true
1942
1955
  });
1943
1956
  const spawnFailed = await bridge.execute({
1944
- query: {
1945
- action: 'call',
1946
- tool: 'lookup',
1947
- arguments: {
1948
- city: 'Dubai'
1949
- }
1957
+ action: 'call',
1958
+ tool: 'lookup',
1959
+ arguments: {
1960
+ city: 'Dubai'
1950
1961
  }
1951
1962
  }, null);
1952
1963
  assert.deepEqual(spawnFailed, {
@@ -1957,12 +1968,10 @@ try {
1957
1968
  spawnReject: true
1958
1969
  });
1959
1970
  const asyncSpawnFailed = await bridge.execute({
1960
- query: {
1961
- action: 'call',
1962
- tool: 'lookup',
1963
- arguments: {
1964
- city: 'Dubai'
1965
- }
1971
+ action: 'call',
1972
+ tool: 'lookup',
1973
+ arguments: {
1974
+ city: 'Dubai'
1966
1975
  }
1967
1976
  }, null);
1968
1977
  assert.deepEqual(asyncSpawnFailed, {
@@ -1973,12 +1982,10 @@ try {
1973
1982
  waitForAbort: true
1974
1983
  });
1975
1984
  const timedOut = await bridge.execute({
1976
- query: {
1977
- action: 'call',
1978
- tool: 'lookup',
1979
- arguments: {
1980
- city: 'Dubai'
1981
- }
1985
+ action: 'call',
1986
+ tool: 'lookup',
1987
+ arguments: {
1988
+ city: 'Dubai'
1982
1989
  }
1983
1990
  }, null);
1984
1991
  assert.deepEqual(timedOut, {
@@ -1987,35 +1994,35 @@ try {
1987
1994
  }, 'deadline abort is surfaced as timed_out');
1988
1995
  assert.equal(timeoutSignal?.aborted, true, 'timeout abort signal is fired');
1989
1996
  const beforeInvalidArgs = spawnSpecs.length;
1990
- assert.deepEqual(await bridge.execute({
1991
- query: {
1997
+ let argsTypeRejected = '';
1998
+ try {
1999
+ await bridge.execute({
1992
2000
  action: 'call',
1993
2001
  tool: 'lookup',
1994
2002
  arguments: [
1995
2003
  'not',
1996
2004
  'plain'
1997
2005
  ]
1998
- }
1999
- }, null), {
2000
- ok: false,
2001
- error: 'invalid_arguments'
2002
- });
2006
+ }, null);
2007
+ } catch (e) {
2008
+ argsTypeRejected = e.name;
2009
+ }
2010
+ assert.equal(argsTypeRejected, 'ToolArgsError', 'arguments 非对象 → 宿主权 schema 结构化拒绝');
2003
2011
  assert.equal(spawnSpecs.length, beforeInvalidArgs, 'non-object arguments are rejected before spawn');
2004
- assert.deepEqual(await bridge.execute({
2005
- query: {
2012
+ let actionRejected = '';
2013
+ try {
2014
+ await bridge.execute({
2006
2015
  action: 'inspect'
2007
- }
2008
- }, null), {
2009
- ok: false,
2010
- error: 'invalid_action'
2011
- }, 'unknown action is rejected structurally');
2016
+ }, null);
2017
+ } catch (e) {
2018
+ actionRejected = e.name;
2019
+ }
2020
+ assert.equal(actionRejected, 'ToolArgsError', '枚举外 action → 宿主权 schema 结构化拒绝(ToolArgsError)');
2012
2021
  const beforeRejected = spawnSpecs.length;
2013
2022
  const rejected = await bridge.execute({
2014
- query: {
2015
- action: 'call',
2016
- tool: 'delete_all',
2017
- arguments: {}
2018
- }
2023
+ action: 'call',
2024
+ tool: 'delete_all',
2025
+ arguments: {}
2019
2026
  }, null);
2020
2027
  assert.deepEqual(rejected, {
2021
2028
  ok: false,
@@ -2105,7 +2112,8 @@ try {
2105
2112
  assert.deepEqual(disabledVariables, [
2106
2113
  'current_date',
2107
2114
  'time_anchor_card',
2108
- 'motivation_brief'
2115
+ 'motivation_brief',
2116
+ 'channel_routing_card'
2109
2117
  ], 'normal product mode keeps its prompt variables');
2110
2118
  const whitespace = [];
2111
2119
  const whitespaceCtx = {
@@ -2462,12 +2470,10 @@ try {
2462
2470
  const legacyBridge = legacyTools.find((tool)=>tool.name === 'gotry_benchmark_environment');
2463
2471
  assert.ok(legacyBridge?.execute, 'legacy config without allowed_output_keys registers the bridge');
2464
2472
  assert.deepEqual(await legacyBridge.execute({
2465
- query: {
2466
- action: 'call',
2467
- tool: 'lookup',
2468
- arguments: {
2469
- city: 'Dubai'
2470
- }
2473
+ action: 'call',
2474
+ tool: 'lookup',
2475
+ arguments: {
2476
+ city: 'Dubai'
2471
2477
  }
2472
2478
  }, null), {
2473
2479
  ok: true,
@@ -3,9 +3,9 @@ import { mkdtempSync, rmSync } from 'node:fs';
3
3
  import { tmpdir } from 'node:os';
4
4
  import { join } from 'node:path';
5
5
  import { ensureLedger } from '../src/state-ledger.js';
6
- import { BookingCopilotTaskRuntimeV2, bookingV2Digest } from '../src/booking-surface/runtime-v2.js';
6
+ import { BookingCopilotTaskRuntime, bookingDigest } from '../src/booking-surface/runtime.js';
7
7
  const workspace = (revision)=>({
8
- schemaVersion: 'booking.surface.v2',
8
+ schemaVersion: 'booking.surface',
9
9
  contextRef: 'ctx-ledger-binding',
10
10
  surface: 'tenant',
11
11
  revision,
@@ -56,7 +56,7 @@ const workspace = (revision)=>({
56
56
  }
57
57
  });
58
58
  const offersReceipt = (actionId, revision)=>({
59
- schemaVersion: 'booking.surface.v2',
59
+ schemaVersion: 'booking.surface',
60
60
  kind: 'action.receipt',
61
61
  actionId,
62
62
  contextRef: 'ctx-ledger-binding',
@@ -82,7 +82,7 @@ const offersReceipt = (actionId, revision)=>({
82
82
  }
83
83
  });
84
84
  const checkReceipt = (actionId, revision)=>({
85
- schemaVersion: 'booking.surface.v2',
85
+ schemaVersion: 'booking.surface',
86
86
  kind: 'action.receipt',
87
87
  actionId,
88
88
  contextRef: 'ctx-ledger-binding',
@@ -108,12 +108,12 @@ const checkReceipt = (actionId, revision)=>({
108
108
  function fixture(stage) {
109
109
  const root = mkdtempSync(join(tmpdir(), 'gotry-availability-ledger-binding-'));
110
110
  const ledger = ensureLedger(root);
111
- const runtime = new BookingCopilotTaskRuntimeV2(ledger, {
111
+ const runtime = new BookingCopilotTaskRuntime(ledger, {
112
112
  contextRefFactory: ()=>'ctx-ledger-binding'
113
113
  });
114
114
  const task = 'ledger-binding-task';
115
115
  runtime.startTask({
116
- schemaVersion: 'booking.surface.v2',
116
+ schemaVersion: 'booking.surface',
117
117
  kind: 'user.turn',
118
118
  taskId: task,
119
119
  turnId: 'turn-1',
@@ -123,7 +123,7 @@ function fixture(stage) {
123
123
  }
124
124
  });
125
125
  const query = {
126
- schemaVersion: 'booking.surface.v2',
126
+ schemaVersion: 'booking.surface',
127
127
  kind: 'offers.query',
128
128
  actionId: 'query-1',
129
129
  contextRef: 'ctx-ledger-binding',
@@ -139,14 +139,14 @@ function fixture(stage) {
139
139
  };
140
140
  runtime.issueOperation(task, query);
141
141
  runtime.continueWithReceipt({
142
- schemaVersion: 'booking.surface.v2',
142
+ schemaVersion: 'booking.surface',
143
143
  kind: 'action.receipt.continuation',
144
144
  taskId: task,
145
145
  workspace: workspace(1),
146
146
  receipt: offersReceipt('query-1', 1)
147
147
  });
148
148
  const check = {
149
- schemaVersion: 'booking.surface.v2',
149
+ schemaVersion: 'booking.surface',
150
150
  kind: 'offer.check',
151
151
  actionId: 'check-1',
152
152
  contextRef: 'ctx-ledger-binding',
@@ -160,7 +160,7 @@ function fixture(stage) {
160
160
  };
161
161
  runtime.issueOperation(task, check);
162
162
  if (stage === 'receipt') runtime.continueWithReceipt({
163
- schemaVersion: 'booking.surface.v2',
163
+ schemaVersion: 'booking.surface',
164
164
  kind: 'action.receipt.continuation',
165
165
  taskId: task,
166
166
  workspace: {
@@ -191,7 +191,7 @@ function rewrite(root, kind, mutate) {
191
191
  }
192
192
  function assertCorrupt(root, label) {
193
193
  const ledger = ensureLedger(root);
194
- const runtime = new BookingCopilotTaskRuntimeV2(ledger, {
194
+ const runtime = new BookingCopilotTaskRuntime(ledger, {
195
195
  contextRefFactory: ()=>'ctx-ledger-binding'
196
196
  });
197
197
  assert.throws(()=>runtime.resumeTask('ledger-binding-task'), /ledger_corrupt:ledger-binding-task/, label);
@@ -200,7 +200,7 @@ function assertCorrupt(root, label) {
200
200
  {
201
201
  const fixtureState = fixture('action');
202
202
  const ledger = ensureLedger(fixtureState.root);
203
- assert.doesNotThrow(()=>new BookingCopilotTaskRuntimeV2(ledger).resumeTask(fixtureState.task));
203
+ assert.doesNotThrow(()=>new BookingCopilotTaskRuntime(ledger).resumeTask(fixtureState.task));
204
204
  ledger.close();
205
205
  rmSync(fixtureState.root, {
206
206
  recursive: true,
@@ -211,28 +211,28 @@ function assertCorrupt(root, label) {
211
211
  'candidate digest',
212
212
  (payload)=>{
213
213
  payload.availability.candidateSetDigest = 'f'.repeat(64);
214
- payload.availabilityDigest = bookingV2Digest(payload.availability);
214
+ payload.availabilityDigest = bookingDigest(payload.availability);
215
215
  }
216
216
  ],
217
217
  [
218
218
  'offer set digest',
219
219
  (payload)=>{
220
220
  payload.availability.hotels.h1.currentGeneration.offerSetDigest = 'e'.repeat(64);
221
- payload.availabilityDigest = bookingV2Digest(payload.availability);
221
+ payload.availabilityDigest = bookingDigest(payload.availability);
222
222
  }
223
223
  ],
224
224
  [
225
225
  'source receipt digest',
226
226
  (payload)=>{
227
227
  payload.availability.hotels.h1.currentGeneration.source.receiptDigest = 'd'.repeat(64);
228
- payload.availabilityDigest = bookingV2Digest(payload.availability);
228
+ payload.availabilityDigest = bookingDigest(payload.availability);
229
229
  }
230
230
  ],
231
231
  [
232
232
  'active ordinal',
233
233
  (payload)=>{
234
234
  payload.availability.activeHotelOrdinal = 1;
235
- payload.availabilityDigest = bookingV2Digest(payload.availability);
235
+ payload.availabilityDigest = bookingDigest(payload.availability);
236
236
  }
237
237
  ],
238
238
  [
@@ -248,12 +248,12 @@ function assertCorrupt(root, label) {
248
248
  evidence: 'conclusive'
249
249
  };
250
250
  payload.availability.availabilityPhase = 'terminal';
251
- payload.availabilityDigest = bookingV2Digest(payload.availability);
251
+ payload.availabilityDigest = bookingDigest(payload.availability);
252
252
  }
253
253
  ]
254
254
  ]){
255
255
  const fixtureState = fixture('action');
256
- rewrite(fixtureState.root, 'booking.copilot.v2.action.issued', mutate);
256
+ rewrite(fixtureState.root, 'booking.copilot.action.issued', mutate);
257
257
  assertCorrupt(fixtureState.root, label);
258
258
  rmSync(fixtureState.root, {
259
259
  recursive: true,
@@ -262,7 +262,7 @@ function assertCorrupt(root, label) {
262
262
  }
263
263
  {
264
264
  const fixtureState = fixture('action');
265
- rewrite(fixtureState.root, 'booking.copilot.v2.action.issued', (payload)=>{
265
+ rewrite(fixtureState.root, 'booking.copilot.action.issued', (payload)=>{
266
266
  payload.availability.activeHotelOrdinal = 1;
267
267
  });
268
268
  assertCorrupt(fixtureState.root, 'raw ACTION availability digest mismatch');
@@ -272,7 +272,7 @@ function assertCorrupt(root, label) {
272
272
  });
273
273
  }{
274
274
  const fixtureState = fixture('receipt');
275
- rewrite(fixtureState.root, 'booking.copilot.v2.receipt.observed', (payload)=>{
275
+ rewrite(fixtureState.root, 'booking.copilot.receipt.observed', (payload)=>{
276
276
  payload.availability.activeHotelOrdinal = 1;
277
277
  });
278
278
  assertCorrupt(fixtureState.root, 'raw RECEIPT availability digest mismatch');
@@ -282,10 +282,10 @@ function assertCorrupt(root, label) {
282
282
  });
283
283
  }{
284
284
  const fixtureState = fixture('action');
285
- rewrite(fixtureState.root, 'booking.copilot.v2.action.issued', (payload)=>{
285
+ rewrite(fixtureState.root, 'booking.copilot.action.issued', (payload)=>{
286
286
  payload.action.input.offerRef = 'o2';
287
287
  const { actionDigest: _ignored, ...base } = payload.action;
288
- payload.action.actionDigest = bookingV2Digest(base);
288
+ payload.action.actionDigest = bookingDigest(base);
289
289
  });
290
290
  assertCorrupt(fixtureState.root, 'wrong action transition');
291
291
  rmSync(fixtureState.root, {
@@ -295,10 +295,10 @@ function assertCorrupt(root, label) {
295
295
  }{
296
296
  const fixtureState = fixture('receipt');
297
297
  const runtimeLedger = ensureLedger(fixtureState.root);
298
- const runtime = new BookingCopilotTaskRuntimeV2(runtimeLedger);
298
+ const runtime = new BookingCopilotTaskRuntime(runtimeLedger);
299
299
  assert.deepEqual(runtime.resumeTask(fixtureState.task)?.availability.criteria, {}, 'recovery retains the canonical offer criteria after restart');
300
300
  const wrongDetour = {
301
- schemaVersion: 'booking.surface.v2',
301
+ schemaVersion: 'booking.surface',
302
302
  kind: 'search.run',
303
303
  actionId: 'detour',
304
304
  contextRef: 'ctx-ledger-binding',
@@ -320,9 +320,9 @@ function assertCorrupt(root, label) {
320
320
  });
321
321
  }{
322
322
  const fixtureState = fixture('receipt');
323
- rewrite(fixtureState.root, 'booking.copilot.v2.receipt.observed', (payload)=>{
323
+ rewrite(fixtureState.root, 'booking.copilot.receipt.observed', (payload)=>{
324
324
  payload.receipt.status = 'applied';
325
- payload.receiptDigest = bookingV2Digest(payload.receipt);
325
+ payload.receiptDigest = bookingDigest(payload.receipt);
326
326
  });
327
327
  assertCorrupt(fixtureState.root, 'wrong receipt transition');
328
328
  rmSync(fixtureState.root, {