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

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 (60) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/bin/gotry-bootstrap.js +83 -37
  4. package/bin/gotry-inner.js +11 -6
  5. package/cordis.gotry-patch.yml +7 -3
  6. package/dist/capabilities/anything.js +62 -29
  7. package/dist/capabilities/doctor.js +25 -3
  8. package/dist/capabilities/hbcli.js +28 -2
  9. package/dist/scripts/agent-planning-turn-deadline-e2e.js +2 -1
  10. package/dist/scripts/anything-tests.js +70 -21
  11. package/dist/scripts/benchmark-environment-bridge-e2e.js +136 -29
  12. package/dist/scripts/benchmark-environment-bridge-tests.js +1056 -269
  13. package/dist/scripts/bootstrap-tests.js +28 -2
  14. package/dist/scripts/doctor-tests.js +55 -1
  15. package/dist/scripts/hbcli-tests.js +38 -1
  16. package/dist/src/benchmark-agent-conformance.js +32 -12
  17. package/dist/src/benchmark-environment-bridge.js +317 -114
  18. package/dist/src/index.js +5 -2
  19. package/extension/manifest.json +2 -2
  20. package/package.json +2 -1
  21. package/ts/capabilities/anything.ts +89 -38
  22. package/ts/capabilities/hbcli.ts +53 -4
  23. package/ts/dsh-runtime/vendor/README.md +60 -0
  24. package/ts/dsh-runtime/vendor/dsh-map-tools/LICENSE +21 -0
  25. package/ts/dsh-runtime/vendor/dsh-map-tools/README.en.md +200 -0
  26. package/ts/dsh-runtime/vendor/dsh-map-tools/README.md +202 -0
  27. package/ts/dsh-runtime/vendor/dsh-map-tools/client/client.js +216 -0
  28. package/ts/dsh-runtime/vendor/dsh-map-tools/cordis.patch.yml +5 -0
  29. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/amap.js +371 -0
  30. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/nominatim.js +63 -0
  31. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/osrm.js +56 -0
  32. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/photon.js +55 -0
  33. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config-file.js +87 -0
  34. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config-route.js +126 -0
  35. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config.js +16 -0
  36. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/index.js +109 -0
  37. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/settings-ns.js +27 -0
  38. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/geocode.js +127 -0
  39. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/poi.js +84 -0
  40. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/routes.js +170 -0
  41. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/amap.d.ts +53 -0
  42. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/nominatim.d.ts +17 -0
  43. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/osrm.d.ts +15 -0
  44. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/photon.d.ts +22 -0
  45. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config-file.d.ts +33 -0
  46. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config-route.d.ts +20 -0
  47. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config.d.ts +23 -0
  48. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/index.d.ts +18 -0
  49. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/settings-ns.d.ts +14 -0
  50. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/geocode.d.ts +11 -0
  51. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/poi.d.ts +9 -0
  52. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/routes.d.ts +16 -0
  53. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/types.d.ts +55 -0
  54. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types.js +16 -0
  55. package/ts/dsh-runtime/vendor/dsh-map-tools/package.json +91 -0
  56. package/ts/package.json +9 -1
  57. package/ts/src/benchmark-agent-conformance.ts +40 -9
  58. package/ts/src/benchmark-environment-bridge.ts +235 -66
  59. package/ts/src/index.ts +4 -2
  60. package/ts/src/turn-deadline.ts +4 -0
@@ -1,6 +1,6 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import { execFileSync, spawnSync } from 'node:child_process';
3
- import { mkdtempSync, readFileSync } from 'node:fs';
3
+ import { mkdirSync, mkdtempSync, readFileSync, writeFileSync } from 'node:fs';
4
4
  import { tmpdir } from 'node:os';
5
5
  import { join } from 'node:path';
6
6
  const repoRoot = join(import.meta.dirname, '..', '..');
@@ -187,7 +187,33 @@ console.log('9. calendar 子命令(setup 状态面 on/off/status + doctor 三态
187
187
  assert.match(r.stderr, /gotry_doctor/, '摘要带对话内指路');
188
188
  assert.match(r.stderr, /扩展=缺/, '缺失项人话=缺(降级类=半可用)');
189
189
  }console.log('10. 启动一次性 doctor 摘要(--summary:stderr 一行/零写盘/恒 exit 0)OK');
190
- console.log('BOOTSTRAP TESTS: 10/10 OK(扩展就位 + 跳过开关 / wizard --dry-run / wizard 真实 / 扩展分发通道 / doctor 体检面 / calendar setup 状态面 / 显式跳过 + auto 跳过 + 单项跳过 / 启动摘要)');
190
+ {
191
+ const sbHome = mkdtempSync(join(tmpdir(), 'gotry-sidebar-test-'));
192
+ const prevHome = process.env.HOME;
193
+ process.env.HOME = sbHome;
194
+ try {
195
+ const { setupSidebar } = await import(bootstrap);
196
+ const r = await setupSidebar(async ()=>{
197
+ const sbPkgDir = join(sbHome, '.dsh/profiles/web/node_modules/dsh-better-sidebar');
198
+ mkdirSync(sbPkgDir, {
199
+ recursive: true
200
+ });
201
+ writeFileSync(join(sbPkgDir, 'package.json'), JSON.stringify({
202
+ name: 'dsh-better-sidebar',
203
+ version: '0.18.0'
204
+ }));
205
+ return {
206
+ ok: false,
207
+ error: 'exit 1'
208
+ };
209
+ });
210
+ assert.equal(r.ok, true, '安装器 exit 非 0 但状态已落盘 → 按落盘判成功(不误报失败)');
211
+ } finally{
212
+ if (prevHome === undefined) delete process.env.HOME;
213
+ else process.env.HOME = prevHome;
214
+ }
215
+ }console.log('11. setupSidebar 落盘状态复核(pnpm 忽略构建脚本 exit 1 不再误报)OK');
216
+ console.log('BOOTSTRAP TESTS: 11/11 OK(扩展就位 + 跳过开关 / wizard --dry-run / wizard 真实 / 扩展分发通道 / doctor 体检面 / calendar setup 状态面 / 显式跳过 + auto 跳过 + 单项跳过 / 启动摘要 / sidebar 落盘状态复核)');
191
217
 
192
218
 
193
219
  //# sourceURL=ts/scripts/bootstrap-tests.ts
@@ -1,7 +1,7 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import { mkdtemp, mkdir, writeFile, rm, readFile } from 'node:fs/promises';
3
3
  import { tmpdir } from 'node:os';
4
- import { join } from 'node:path';
4
+ import { dirname, join } from 'node:path';
5
5
  import { runDoctorChecks, renderDoctorReportMd, nodeOk } from '../capabilities/doctor.js';
6
6
  import { apply } from '../src/index.js';
7
7
  const tmp = await mkdtemp(join(tmpdir(), 'gotry-doctor-test-'));
@@ -78,6 +78,60 @@ assert.match(md, /flyai\.open\.fliggy\.com 控制台申请正式 key/, 'prose
78
78
  assert.ok(!md.includes('`到 flyai'), 'prose 类 fix 不应整体包反引号');
79
79
  assert.match(md, /LLM key/, '让渡面(LLM key)照常入表');
80
80
  console.log('5. 报告渲染 OK');
81
+ {
82
+ const hoist = await mkdtemp(join(tmpdir(), 'gotry-doctor-hoist-'));
83
+ const pkgRoot = join(hoist, 'node_modules', '@danceiny', 'gotry');
84
+ await mkdir(pkgRoot, {
85
+ recursive: true
86
+ });
87
+ await writeFile(join(pkgRoot, 'package.json'), JSON.stringify({
88
+ name: '@danceiny/gotry',
89
+ version: '0.0.1-test'
90
+ }), 'utf-8');
91
+ const stubPkg = async (dir, main)=>{
92
+ await mkdir(join(hoist, 'node_modules', dir, 'lib'), {
93
+ recursive: true
94
+ });
95
+ await writeFile(join(hoist, 'node_modules', dir, 'package.json'), JSON.stringify({
96
+ name: dir,
97
+ version: '0.0.0-test',
98
+ main
99
+ }), 'utf-8');
100
+ await writeFile(join(hoist, 'node_modules', dir, main), '// stub\n', 'utf-8');
101
+ };
102
+ await stubPkg('dsh-map-tools', 'lib/index.js');
103
+ await stubPkg('@deepseek-ai/dsh', 'lib/bin.js');
104
+ await stubPkg('@deepseek-ai/dsh-tool-ask-user', 'lib/index.js');
105
+ const rb = await runDoctorChecks({
106
+ repoRoot: pkgRoot,
107
+ homeDir: join(hoist, 'home-empty'),
108
+ env: {}
109
+ });
110
+ assert.equal(rb.items.find((i)=>i.id === 'map-tools').status, 'ok', '提升布局 map-tools 经包根解析链命中');
111
+ assert.equal(rb.items.find((i)=>i.id === 'ask-user').status, 'ok', '提升布局 ask-user 经 dsh 上下文解析链命中(误报修复)');
112
+ await rm(hoist, {
113
+ recursive: true,
114
+ force: true
115
+ });
116
+ }console.log('5b. npm 提升布局解析链(map-tools/ask-user 误报修复)OK');
117
+ {
118
+ const vend = await mkdtemp(join(tmpdir(), 'gotry-doctor-vendor-'));
119
+ const vendorEntry = join(vend, 'ts/dsh-runtime/vendor/dsh-map-tools/lib/index.js');
120
+ await mkdir(dirname(vendorEntry), {
121
+ recursive: true
122
+ });
123
+ await writeFile(vendorEntry, '// stub\n', 'utf-8');
124
+ const rc = await runDoctorChecks({
125
+ repoRoot: vend,
126
+ homeDir: join(vend, 'home-empty'),
127
+ env: {}
128
+ });
129
+ assert.equal(rc.items.find((i)=>i.id === 'map-tools').status, 'ok', 'vendor 副本命中(map-tools 随 tarball 分发)');
130
+ await rm(vend, {
131
+ recursive: true,
132
+ force: true
133
+ });
134
+ }console.log('5c. 随包 vendor 布局(map-tools tarball 分发面)OK');
81
135
  const smokeRoot = await mkdtemp(join(tmpdir(), 'gotry-doctor-state-'));
82
136
  const registered = [];
83
137
  const ctx = {
@@ -86,7 +86,44 @@ await writeFile(fallback, JSON.stringify({
86
86
  if (!argLine.includes('destination-name') || !argLine.includes('room-occupancies')) {
87
87
  throw new Error(`FAIL: v0.3.0 旗标未对齐,实际 ${argLine.slice(0, 200)}`);
88
88
  }
89
- console.log('5. v0.3.0 旗标(--destination-name/--room-occupancies)对齐 OK');
89
+ const rd = await searchHotels({
90
+ destination: '普吉',
91
+ checkIn: '2026-09-18',
92
+ checkOut: '2026-09-20'
93
+ }, {
94
+ hbcliBin: echoBin
95
+ });
96
+ const dateLine = JSON.stringify(rd);
97
+ if (!dateLine.includes('check-in') || !dateLine.includes('2026-09-18') || !dateLine.includes('check-out')) {
98
+ throw new Error(`FAIL: 日期旗标未传上游,实际 ${dateLine.slice(0, 240)}`);
99
+ }
100
+ assert.ok(rd.summary.includes('入住 2026-09-18 → 退房 2026-09-20'), 'summary 应回显日期槽位');
101
+ console.log('5. 旗标对齐(--destination-name/--room-occupancies/--check-in/--check-out)OK');
102
+ }{
103
+ const { writeFileSync, chmodSync } = await import('node:fs');
104
+ const listBin = join(tmp, 'hbcli-list');
105
+ writeFileSync(listBin, `#!/bin/sh
106
+ cat <<'JSON'
107
+ {"list":[{"id":461850557,"name":{"en":"Jumeirah Beach Hotel","zh":"朱美拉海滩酒店"},"star":5,"minPrice":{"amount":100,"currency":"USD"}}],"basic":{"sessionId":"s1"}}
108
+ JSON
109
+ `);
110
+ chmodSync(listBin, 0o755);
111
+ const rl = await searchHotels({
112
+ destination: '迪拜',
113
+ checkIn: '2026-09-18',
114
+ checkOut: '2026-09-20'
115
+ }, {
116
+ hbcliBin: listBin
117
+ });
118
+ assert.equal(rl.via, 'hbcli-realtime');
119
+ assert.ok(rl.summary.includes('实时 1 家'), 'summary 应带家数');
120
+ assert.ok(rl.summary.includes('id=461850557'), '数据行应带 hotelId(hotel-rates 入参来源)');
121
+ assert.ok(rl.summary.includes('朱美拉海滩酒店'), '数据行应带 zh 名称');
122
+ assert.ok(rl.summary.includes('5★'), '数据行应带星级');
123
+ assert.ok(rl.summary.includes('100 USD'), '数据行应带最低价');
124
+ assert.match(rl.summary, /\[实时API:hbcli@/, 'summary 应带证据链时间戳');
125
+ assert.ok(rl.hotels !== null, 'hotels 结构化产物保留(UI/程序消费)');
126
+ console.log(`5b. 实时 summary 数据行 OK:${rl.summary.split('\n')[1]}`);
90
127
  }const r4 = await searchHotels({
91
128
  destination: '普吉岛'
92
129
  }, {
@@ -12,6 +12,13 @@ export const BENCHMARK_BRIDGE_RETRY_CALL_NOT_ALLOWED = 'BENCHMARK_BRIDGE_RETRY_C
12
12
  export const BENCHMARK_CONFORMANCE_STATE_UNAVAILABLE = 'BENCHMARK_CONFORMANCE_STATE_UNAVAILABLE';
13
13
  const IDENTIFIER = /^[A-Za-z][A-Za-z0-9_.-]*$/;
14
14
  const MAX_TERMINAL_BYTES = 1024 * 1024;
15
+ const BENCHMARK_TOOL_RESULT_SCHEMA_VERSION = 'gotry_benchmark_tool_result_v1';
16
+ const BENCHMARK_DOMAIN_RECOVERIES = new Set([
17
+ 'none',
18
+ 'retry_same',
19
+ 'revise_arguments',
20
+ 'choose_alternative'
21
+ ]);
15
22
  function plainObject(value) {
16
23
  return typeof value === 'object' && value !== null && !Array.isArray(value);
17
24
  }
@@ -90,13 +97,23 @@ function bridgeResultStatus(data, callId) {
90
97
  try {
91
98
  const parsed = JSON.parse(text);
92
99
  if (!plainObject(parsed)) return undefined;
93
- if (parsed.ok === true) return {
94
- ok: true
100
+ const keys = Object.keys(parsed).sort().join(',');
101
+ if (parsed.ok === true && keys === 'ok,result' && (plainObject(parsed.result) || Array.isArray(parsed.result))) return {
102
+ kind: 'result'
95
103
  };
104
+ if (parsed.ok === true && keys === 'ok,outcome' && plainObject(parsed.outcome)) {
105
+ const outcomeKeys = Object.keys(parsed.outcome).sort().join(',');
106
+ if (outcomeKeys === 'code,recovery,schema_version,status' && parsed.outcome.schema_version === BENCHMARK_TOOL_RESULT_SCHEMA_VERSION && (parsed.outcome.status === 'miss' || parsed.outcome.status === 'error') && typeof parsed.outcome.code === 'string' && IDENTIFIER.test(parsed.outcome.code) && typeof parsed.outcome.recovery === 'string' && BENCHMARK_DOMAIN_RECOVERIES.has(parsed.outcome.recovery)) return {
107
+ kind: 'domain'
108
+ };
109
+ return undefined;
110
+ }
96
111
  if (parsed.ok === false && typeof parsed.error === 'string') {
112
+ const exactFailure = parsed.error === 'runner_failed' ? keys === 'error,ok' || keys === 'error,exit_code,ok,signal' && (parsed.exit_code === null || typeof parsed.exit_code === 'number' && Number.isInteger(parsed.exit_code)) && (parsed.signal === null || typeof parsed.signal === 'string') : parsed.error === 'invalid_arguments' ? keys === 'error,ok,reason' && typeof parsed.reason === 'string' : keys === 'error,ok';
113
+ if (!exactFailure) return undefined;
97
114
  const code = parsed.error === 'timed_out' ? BENCHMARK_BRIDGE_TIMED_OUT : parsed.error === 'runner_failed' ? BENCHMARK_BRIDGE_RUNNER_FAILED : parsed.error === 'spawn_failed' ? BENCHMARK_BRIDGE_SPAWN_FAILED : parsed.error === 'output_truncated' ? BENCHMARK_BRIDGE_OUTPUT_TRUNCATED : BENCHMARK_BRIDGE_CALL_FAILED;
98
115
  return {
99
- ok: false,
116
+ kind: 'failure',
100
117
  code
101
118
  };
102
119
  }
@@ -164,8 +181,11 @@ export function createBenchmarkAgentConformance(projection) {
164
181
  const callId = event.data.message.source.callId;
165
182
  if (typeof callId !== 'string' || !state.validCallIds.has(callId)) return;
166
183
  const resultStatus = bridgeResultStatus(event.data, callId);
167
- if (resultStatus?.ok === true) {
184
+ if (typeof event.data.step === 'number') state.lastBridgeResponseStep = event.data.step;
185
+ if (resultStatus?.kind === 'result') {
168
186
  state.successfulResultStep = typeof event.data.step === 'number' ? event.data.step : state.successfulResultStep;
187
+ } else if (resultStatus?.kind === 'domain') {
188
+ state.domainOutcomeStep = typeof event.data.step === 'number' ? event.data.step : state.domainOutcomeStep;
169
189
  } else {
170
190
  state.bridgeCallFailed = true;
171
191
  state.bridgeFailureCode = resultStatus?.code ?? BENCHMARK_BRIDGE_CALL_FAILED;
@@ -194,13 +214,13 @@ export function createBenchmarkAgentConformance(projection) {
194
214
  code: BENCHMARK_BRIDGE_RETRY_CALL_NOT_ALLOWED
195
215
  };
196
216
  }
197
- if (state.successfulResultStep === undefined) {
198
- if (state.bridgeCallFailed) {
199
- return {
200
- kind: 'reject',
201
- code: state.bridgeFailureCode ?? BENCHMARK_BRIDGE_CALL_FAILED
202
- };
203
- }
217
+ if (state.bridgeCallFailed && state.successfulResultStep === undefined) {
218
+ return {
219
+ kind: 'reject',
220
+ code: state.bridgeFailureCode ?? BENCHMARK_BRIDGE_CALL_FAILED
221
+ };
222
+ }
223
+ if (state.successfulResultStep === undefined && state.domainOutcomeStep === undefined) {
204
224
  if (state.retryCount >= MAX_CONFORMANCE_RETRIES) {
205
225
  return {
206
226
  kind: 'reject',
@@ -215,7 +235,7 @@ export function createBenchmarkAgentConformance(projection) {
215
235
  };
216
236
  }
217
237
  const terminal = state.lastAssistant;
218
- const terminalIsValid = terminal !== undefined && !terminal.interrupted && terminal.step > state.successfulResultStep && parseBenchmarkTerminal(terminal.text, projection.terminal).ok;
238
+ const terminalIsValid = terminal !== undefined && !terminal.interrupted && terminal.step > state.lastBridgeResponseStep && parseBenchmarkTerminal(terminal.text, projection.terminal).ok;
219
239
  if (terminalIsValid) return {
220
240
  kind: 'accept'
221
241
  };