@danceiny/gotry 0.0.1-rc.16 → 0.0.1-rc.17
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.
- package/README.md +47 -13
- package/README.zh-CN.md +20 -10
- package/bin/gotry-booking-copilot.js +53 -0
- package/bin/gotry-bootstrap.js +111 -51
- package/bin/gotry-inner.js +442 -60
- package/bin/gotry-runtime-resolution.d.ts +27 -0
- package/bin/gotry-runtime-resolution.js +50 -0
- package/bin/gotry.js +1 -1
- package/cordis.gotry-patch.yml +5 -1
- package/dist/capabilities/agent-reach-deep.js +1 -1
- package/dist/capabilities/agent-reach.js +1 -1
- package/dist/capabilities/anything.js +1 -1
- package/dist/capabilities/artifacts.js +1 -1
- package/dist/capabilities/effect.js +1 -1
- package/dist/capabilities/fact-log.js +1 -1
- package/dist/capabilities/flyai.js +20 -6
- package/dist/capabilities/hbcli.js +1 -1
- package/dist/capabilities/incident-log.js +1 -1
- package/dist/capabilities/model-override.js +18 -0
- package/dist/capabilities/opensky.js +1 -1
- package/dist/capabilities/resilience.js +1 -1
- package/dist/capabilities/session/action-cache.js +1 -1
- package/dist/capabilities/session/adapters/ctrip-flight.js +1 -1
- package/dist/capabilities/session/adapters/meituan-local.js +1 -1
- package/dist/capabilities/session/benchmark.js +1 -1
- package/dist/capabilities/session/extension-bridge.js +19 -6
- package/dist/capabilities/session/extension-channel.js +3 -3
- package/dist/capabilities/session/extension-distribution.js +234 -0
- package/dist/capabilities/session/extract.js +1 -1
- package/dist/capabilities/session/golden-score.js +92 -0
- package/dist/capabilities/session/health-watch.js +1 -1
- package/dist/capabilities/session/read-guard.js +1 -1
- package/dist/capabilities/session/static-flight-golden.js +137 -0
- package/dist/capabilities/session/transport.js +1 -1
- package/dist/capabilities/session/wizard.js +21 -251
- package/dist/capabilities/session-consent.js +1 -1
- package/dist/capabilities/session-login.js +11 -5
- package/dist/capabilities/session-search.js +46 -4
- package/dist/capabilities/weather.js +168 -46
- package/dist/data/session-golden-20.json +25 -0
- package/dist/data/sf-golden-manifest.json +102 -0
- package/dist/data/sf-static-routes.json +91 -0
- package/dist/scripts/action-cache-tests.js +1 -1
- package/dist/scripts/agent-planning-budget-e2e.js +227 -0
- package/dist/scripts/agent-planning-budget-tests.js +173 -0
- package/dist/scripts/agent-reach-deep-tests.js +1 -1
- package/dist/scripts/agent-reach-tests.js +1 -1
- package/dist/scripts/agent-reach-wrapper-tests.js +1 -1
- package/dist/scripts/anything-tests.js +1 -1
- package/dist/scripts/async-collect.js +1 -1
- package/dist/scripts/benchmark-environment-bridge-e2e.js +981 -0
- package/dist/scripts/benchmark-environment-bridge-tests.js +2544 -0
- package/dist/scripts/booking-copilot-availability-ledger-binding-tests.js +335 -0
- package/dist/scripts/booking-copilot-availability-policy-v2-tests.js +1355 -0
- package/dist/scripts/booking-copilot-bin-proof-tests.js +89 -0
- package/dist/scripts/booking-copilot-crossrepo-fixture-server.js +113 -0
- package/dist/scripts/booking-copilot-dsh-core-proof-tests.js +356 -0
- package/dist/scripts/booking-copilot-dsh-planner-proof-tests.js +557 -0
- package/dist/scripts/booking-copilot-dsh-plugin-proof-tests.js +140 -0
- package/dist/scripts/booking-copilot-event-sequence-concurrency-proof-tests.js +202 -0
- package/dist/scripts/booking-copilot-gap-code-contract-proof-tests.js +102 -0
- package/dist/scripts/booking-copilot-operation-ledger-concurrency-proof-tests.js +374 -0
- package/dist/scripts/booking-copilot-receipt-ledger-concurrency-proof-tests.js +447 -0
- package/dist/scripts/booking-copilot-runtime-proof-tests.js +205 -0
- package/dist/scripts/booking-copilot-server-proof-tests.js +317 -0
- package/dist/scripts/booking-copilot-startup-proof-tests.js +283 -0
- package/dist/scripts/booking-copilot-v2-runtime-proof-tests.js +3935 -0
- package/dist/scripts/booking-saga-tests.js +1 -1
- package/dist/scripts/booking-surface-contract-proof-tests.js +393 -0
- package/dist/scripts/booking-surface-v2-contract-proof-tests.js +1174 -0
- package/dist/scripts/bootstrap-tests.js +30 -10
- package/dist/scripts/build-changelog.js +1 -1
- package/dist/scripts/changelog-tests.js +1 -1
- package/dist/scripts/companion-tests.js +1 -1
- package/dist/scripts/diff-test.js +1 -1
- package/dist/scripts/dsh-runtime-closure-tests.js +225 -0
- package/dist/scripts/dsh-runtime-closure.js +150 -0
- package/dist/scripts/effect-tests.js +1 -1
- package/dist/scripts/engine-run.js +1 -1
- package/dist/scripts/engine-tests.js +1 -1
- package/dist/scripts/evaluation-cadence-tests.js +347 -0
- package/dist/scripts/evaluation-contract-tests.js +574 -0
- package/dist/scripts/extension-distribution-cli.js +35 -0
- package/dist/scripts/extension-distribution-tests.js +341 -0
- package/dist/scripts/extension-tests.js +128 -23
- package/dist/scripts/fact-gate-tests.js +1 -1
- package/dist/scripts/flyai-tests.js +1 -1
- package/dist/scripts/hbcli-e2e-tests.js +1 -1
- package/dist/scripts/hbcli-tests.js +1 -1
- package/dist/scripts/health-watch-cli.js +1 -1
- package/dist/scripts/i18n-tests.js +1 -1
- package/dist/scripts/incident-tests.js +1 -1
- package/dist/scripts/journey-tests.js +1 -1
- package/dist/scripts/ledger-tests.js +1 -1
- package/dist/scripts/ledger-workflow-crash.js +1 -1
- package/dist/scripts/memory-capture-tests.js +1 -1
- package/dist/scripts/memory-decay-tests.js +1 -1
- package/dist/scripts/memory-metrics.js +1 -1
- package/dist/scripts/memory-value-report.js +1 -1
- package/dist/scripts/model-override-e2e.js +176 -0
- package/dist/scripts/nightly-evidence-tests.js +1 -1
- package/dist/scripts/nightly-evidence.js +1 -1
- package/dist/scripts/nudge-digest.js +1 -1
- package/dist/scripts/onboarding-tests.js +21 -53
- package/dist/scripts/opensky-check.js +1 -1
- package/dist/scripts/opensky-tests.js +1 -1
- package/dist/scripts/pnpm-dsh-closure-proof.js +20 -0
- package/dist/scripts/price-drift-tests.js +1 -1
- package/dist/scripts/price-drift-watch.js +1 -1
- package/dist/scripts/probe-poi-tests.js +1 -1
- package/dist/scripts/product-metrics.js +1 -1
- package/dist/scripts/publish-preverify.js +40 -4
- package/dist/scripts/realtime-pricing-tests.js +1 -1
- package/dist/scripts/replay-async.js +1 -1
- package/dist/scripts/replay-real.js +1 -1
- package/dist/scripts/replay.js +1 -1
- package/dist/scripts/session-attach-diagnose.js +1 -1
- package/dist/scripts/session-attach-poc.js +1 -1
- package/dist/scripts/session-benchmark.js +1 -1
- package/dist/scripts/session-extract-tests.js +1 -1
- package/dist/scripts/session-login.js +1 -1
- package/dist/scripts/session-tests.js +70 -20
- package/dist/scripts/sf-live-benchmark.js +338 -0
- package/dist/scripts/sf-live-cli-tests.js +21 -0
- package/dist/scripts/sf-soft-score-tests.js +108 -0
- package/dist/scripts/sf-summary.js +93 -0
- package/dist/scripts/skeleton-check.js +1 -1
- package/dist/scripts/skeleton-integration-test.js +1 -1
- package/dist/scripts/skills-contract-tests.js +1 -1
- package/dist/scripts/smoke-session-gate-tests.js +29 -0
- package/dist/scripts/smoke.js +79 -33
- package/dist/scripts/state-cli-tests.js +1 -1
- package/dist/scripts/state-cli.js +1 -1
- package/dist/scripts/static-golden-tests.js +299 -0
- package/dist/scripts/time-eval-tests.js +1 -1
- package/dist/scripts/travel-timeline-tests.js +1 -1
- package/dist/scripts/unified-tests.js +1 -1
- package/dist/scripts/weather-tests.js +694 -44
- package/dist/scripts/z3-race-tests.js +1 -1
- package/dist/src/artifact-gate.js +1 -1
- package/dist/src/benchmark-agent-conformance.js +370 -0
- package/dist/src/benchmark-environment-bridge.js +384 -0
- package/dist/src/benchmark-headless-child-diagnostics.js +173 -0
- package/dist/src/benchmark-tool-isolation.js +124 -0
- package/dist/src/bookable-facts.js +1 -1
- package/dist/src/booking-saga.js +1 -1
- package/dist/src/booking-surface/availability-policy-v2.js +830 -0
- package/dist/src/booking-surface/canonical-schema.js +113 -0
- package/dist/src/booking-surface/contracts-v2.js +89 -0
- package/dist/src/booking-surface/contracts.js +46 -0
- package/dist/src/booking-surface/dsh-planner.js +453 -0
- package/dist/src/booking-surface/dsh-plugin.js +93 -0
- package/dist/src/booking-surface/error-codes.js +94 -0
- package/dist/src/booking-surface/index.js +15 -0
- package/dist/src/booking-surface/profile.js +68 -0
- package/dist/src/booking-surface/runtime-v2.js +1771 -0
- package/dist/src/booking-surface/runtime.js +351 -0
- package/dist/src/booking-surface/server-v2.js +334 -0
- package/dist/src/booking-surface/server.js +302 -0
- package/dist/src/booking-surface/startup.js +159 -0
- package/dist/src/booking-surface/validation-v2.js +319 -0
- package/dist/src/booking-surface/validation.js +809 -0
- package/dist/src/bridge.js +1 -1
- package/dist/src/companions.js +1 -1
- package/dist/src/contracts.js +1 -1
- package/dist/src/dsh-llm.js +1 -1
- package/dist/src/engine.js +1 -1
- package/dist/src/evaluation-cadence.js +234 -0
- package/dist/src/evaluation-contracts.js +906 -0
- package/dist/src/i18n.js +1 -1
- package/dist/src/index.js +50 -19
- package/dist/src/journey.js +1 -1
- package/dist/src/loop.js +1 -1
- package/dist/src/memory-capture.js +1 -1
- package/dist/src/memory-decay.js +1 -1
- package/dist/src/memory-utility.js +1 -1
- package/dist/src/mock-llm.js +1 -1
- package/dist/src/model.js +1 -1
- package/dist/src/realtime-pricing.js +1 -1
- package/dist/src/slot-spec.js +1 -1
- package/dist/src/state-ledger.js +2 -1
- package/dist/src/time-anchor.js +1 -1
- package/dist/src/tool-budget.js +136 -0
- package/dist/src/tool-packet.js +1 -1
- package/dist/src/travel-slots.js +1 -1
- package/dist/src/travel-timeline.js +1 -1
- package/dist/src/unified.js +1 -1
- package/dist/src/wish-pool.js +1 -1
- package/dist/src/z3-shared.js +1 -1
- package/extension/README.md +31 -7
- package/package.json +286 -11
- package/schemas/booking.surface.v1.schema.json +927 -0
- package/schemas/booking.surface.v2.schema.json +61 -0
- package/ts/capabilities/flyai.ts +16 -3
- package/ts/capabilities/session/extension-bridge.ts +37 -14
- package/ts/capabilities/session/extension-channel.ts +6 -3
- package/ts/capabilities/session/extension-distribution.ts +264 -0
- package/ts/capabilities/session/golden-score.ts +139 -0
- package/ts/capabilities/session/health-watch.ts +1 -1
- package/ts/capabilities/session/static-flight-golden.ts +209 -0
- package/ts/capabilities/session/wizard.ts +34 -176
- package/ts/capabilities/session-login.ts +15 -5
- package/ts/capabilities/session-search.ts +40 -3
- package/ts/capabilities/weather.ts +141 -52
- package/ts/package.json +3 -3
- package/ts/src/benchmark-agent-conformance.ts +448 -0
- package/ts/src/benchmark-environment-bridge.ts +348 -0
- package/ts/src/benchmark-headless-child-diagnostics.ts +184 -0
- package/ts/src/benchmark-tool-isolation.ts +166 -0
- package/ts/src/booking-surface/availability-policy-v2.ts +523 -0
- package/ts/src/booking-surface/canonical-schema.js +113 -0
- package/ts/src/booking-surface/contracts-v2.ts +118 -0
- package/ts/src/booking-surface/contracts.ts +380 -0
- package/ts/src/booking-surface/dsh-planner.ts +452 -0
- package/ts/src/booking-surface/dsh-plugin.js +93 -0
- package/ts/src/booking-surface/error-codes.ts +101 -0
- package/ts/src/booking-surface/index.ts +12 -0
- package/ts/src/booking-surface/profile.ts +42 -0
- package/ts/src/booking-surface/runtime-v2.ts +1466 -0
- package/ts/src/booking-surface/runtime.ts +483 -0
- package/ts/src/booking-surface/server-v2.ts +247 -0
- package/ts/src/booking-surface/server.ts +324 -0
- package/ts/src/booking-surface/startup.ts +196 -0
- package/ts/src/booking-surface/validation-v2.ts +205 -0
- package/ts/src/booking-surface/validation.ts +453 -0
- package/ts/src/index.ts +64 -11
- package/ts/src/state-ledger.ts +1 -0
- package/ts/src/tool-budget.ts +165 -0
- package/dist/scripts/wizard-bootstrap.js +0 -32
package/dist/scripts/smoke.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { apply } from '../src/index.js';
|
|
4
|
+
import { installModelOverride } from '../capabilities/model-override.js';
|
|
5
|
+
import { offlineSessionFlightResult, sessionLiveEnabled } from '../capabilities/session-search.js';
|
|
4
6
|
async function main() {
|
|
5
7
|
const { mkdtempSync, rmSync } = await import('node:fs');
|
|
6
8
|
const { tmpdir } = await import('node:os');
|
|
@@ -36,18 +38,17 @@ async function main() {
|
|
|
36
38
|
return t;
|
|
37
39
|
};
|
|
38
40
|
const motivation = byName('gotry_motivation_save');
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
escape_rest: 0.7
|
|
44
|
-
}
|
|
41
|
+
const rejectedMotivation = await motivation.execute({
|
|
42
|
+
profile: {
|
|
43
|
+
weights: {
|
|
44
|
+
escape_rest: 0.7
|
|
45
45
|
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
}
|
|
47
|
+
}, null);
|
|
48
|
+
if (rejectedMotivation.ok !== false || !rejectedMotivation.summary?.includes('without evidence')) {
|
|
49
|
+
throw new Error(`FAIL: profile without evidence should have been rejected, actual ${JSON.stringify(rejectedMotivation).slice(0, 120)}`);
|
|
50
50
|
}
|
|
51
|
+
console.log(`motivation without evidence rejected: ${rejectedMotivation.summary.slice(0, 80)}...`);
|
|
51
52
|
const saved = await motivation.execute({
|
|
52
53
|
profile: {
|
|
53
54
|
weights: {
|
|
@@ -296,10 +297,10 @@ async function main() {
|
|
|
296
297
|
date: '2026-10-01'
|
|
297
298
|
}
|
|
298
299
|
}, null);
|
|
299
|
-
const faBlocked = fa.verdict === 'error' && /sentinel|block/i.test(fa.error ?? '');
|
|
300
|
+
const faBlocked = fa.verdict === 'error' && /sentinel|block|trial limit/i.test(fa.error ?? '');
|
|
300
301
|
const faErrTerminal = fa.ok === false && fa.verdict === 'error' && /^flyai-error$/.test(String(fa.via ?? '')) && /\[实时API:flyai@error@/.test(String(fa.evidence ?? ''));
|
|
301
302
|
if (faBlocked) {
|
|
302
|
-
console.log(' WARN - flyai Sentinel
|
|
303
|
+
console.log(' WARN - flyai 上游限流中(Sentinel/trial-limit 429),降级合同通过(hit 断言跳过)');
|
|
303
304
|
} else if (faErrTerminal) {
|
|
304
305
|
console.log(' WARN - flyai 端点不可达(超时/降级),证据链合同通过(hit 断言跳过)');
|
|
305
306
|
} else if (fa.ok !== true || fa.verdict !== 'hit' || (fa.options?.length ?? 0) < 1 || !/\[实时API:flyai@/.test(fa.evidence ?? '')) {
|
|
@@ -317,30 +318,36 @@ async function main() {
|
|
|
317
318
|
if (!(faPast.ok === false && /已是过去/.test(String(faPast.summary ?? '')))) {
|
|
318
319
|
throw new Error(`FAIL: flyai 过去日期应代码层预校验拒绝,实际:${JSON.stringify(faPast).slice(0, 200)}`);
|
|
319
320
|
}
|
|
320
|
-
const previousChromeUserDataDir = process.env.CHROME_USER_DATA_DIR;
|
|
321
|
-
process.env.CHROME_USER_DATA_DIR = prof;
|
|
322
321
|
let ss;
|
|
323
|
-
|
|
324
|
-
ss =
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
}
|
|
322
|
+
if (!sessionLiveEnabled()) {
|
|
323
|
+
ss = offlineSessionFlightResult();
|
|
324
|
+
console.log(' OFFLINE - GOTRY_SESSION_LIVE!=1: session transport was not invoked');
|
|
325
|
+
} else {
|
|
326
|
+
const previousChromeUserDataDir = process.env.CHROME_USER_DATA_DIR;
|
|
327
|
+
process.env.CHROME_USER_DATA_DIR = prof;
|
|
328
|
+
try {
|
|
329
|
+
ss = await byName('gotry_session_search').execute({
|
|
330
|
+
query: {
|
|
331
|
+
from: '上海',
|
|
332
|
+
to: '丽江',
|
|
333
|
+
date: '2026-10-01'
|
|
334
|
+
}
|
|
335
|
+
}, null);
|
|
336
|
+
} finally{
|
|
337
|
+
if (previousChromeUserDataDir === undefined) delete process.env.CHROME_USER_DATA_DIR;
|
|
338
|
+
else process.env.CHROME_USER_DATA_DIR = previousChromeUserDataDir;
|
|
339
|
+
}
|
|
338
340
|
}
|
|
341
|
+
rmSync(prof, {
|
|
342
|
+
recursive: true,
|
|
343
|
+
force: true
|
|
344
|
+
});
|
|
339
345
|
const ssErrTerminal = ss.ok === false && /^session-[a-z0-9-]+-error$/.test(String(ss.via ?? '')) && !!ss.evidence;
|
|
340
346
|
if (!(ss.verdict === 'needs-login' || ss.verdict === 'needs-attach' || ss.verdict === 'hit' || ss.verdict === 'cooldown' || ss.verdict === 'challenged') && !ssErrTerminal) {
|
|
341
347
|
throw new Error(`FAIL: session 工具终态应属 {needs-attach,needs-login,hit,cooldown,challenged} 或带证据的 error 终态,实际:${JSON.stringify(ss).slice(0, 200)}`);
|
|
342
348
|
}
|
|
343
|
-
|
|
349
|
+
const faOutcome = faBlocked ? 'sentinel-限流降级' : faErrTerminal ? '端点不可达降级' : `live hit(${fa.options?.length ?? 0} 条)`;
|
|
350
|
+
console.log(`session-face tools: flyai ${faOutcome}; session cdp 隔离门禁=needs-attach`);
|
|
344
351
|
const fh = await byName('gotry_flyai_search').execute({
|
|
345
352
|
query: {
|
|
346
353
|
kind: 'hotel',
|
|
@@ -349,7 +356,7 @@ async function main() {
|
|
|
349
356
|
checkOut: '2026-10-03'
|
|
350
357
|
}
|
|
351
358
|
}, null);
|
|
352
|
-
const fhBlocked = fh.verdict === 'error' && /sentinel|block/i.test(fh.error ?? '');
|
|
359
|
+
const fhBlocked = fh.verdict === 'error' && /sentinel|block|trial limit/i.test(fh.error ?? '');
|
|
353
360
|
const fhErrTerminal = fh.ok === false && fh.verdict === 'error' && /^flyai-error$/.test(String(fh.via ?? '')) && /\[实时API:flyai@error@/.test(String(fh.evidence ?? ''));
|
|
354
361
|
if (fhBlocked || fhErrTerminal) {
|
|
355
362
|
console.log(' WARN - flyai hotel 限流/端点降级,证据链合同通过(hit 断言跳过)');
|
|
@@ -373,7 +380,8 @@ async function main() {
|
|
|
373
380
|
if (!(fhPast.ok === false && /不是未来合法区间/.test(String(fhPast.summary ?? '')))) {
|
|
374
381
|
throw new Error(`FAIL: 酒店过去入住日应代码层预校验拒绝,实际:${JSON.stringify(fhPast).slice(0, 200)}`);
|
|
375
382
|
}
|
|
376
|
-
|
|
383
|
+
const fhOutcome = fhBlocked ? 'sentinel-限流降级' : fhErrTerminal ? '端点不可达降级' : `${fh.hotels?.length ?? 0} 家`;
|
|
384
|
+
console.log(` hotel channel: ${fhOutcome}; 参数闸/过去日闸生效`);
|
|
377
385
|
}
|
|
378
386
|
{
|
|
379
387
|
const gate = preExecutes.at(-1);
|
|
@@ -568,6 +576,44 @@ async function main() {
|
|
|
568
576
|
if (!view?.title?.includes('blocked')) throw new Error(`FAIL: blocked 呈现卡标题应含 blocked,实际:${view?.title}`);
|
|
569
577
|
console.log(`fact gate: registry 1+1(hit/miss);verified 措辞 pass;miss 填充 UO784 blocked(not_in_source) + 呈现卡`);
|
|
570
578
|
}
|
|
579
|
+
{
|
|
580
|
+
const none = [];
|
|
581
|
+
const ctxNone = {
|
|
582
|
+
on: (_e, fn)=>{
|
|
583
|
+
none.push(fn);
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
if (installModelOverride(ctxNone, {}) !== false || none.length !== 0) {
|
|
587
|
+
throw new Error('FAIL: 未设 GOTRY_LLM_MODEL 时不得挂 agent/request 覆盖');
|
|
588
|
+
}
|
|
589
|
+
if (installModelOverride({}, {
|
|
590
|
+
GOTRY_LLM_MODEL: 'MiniMax-M2'
|
|
591
|
+
}) !== false) {
|
|
592
|
+
throw new Error('FAIL: 无事件总线宿主应返回 false 而非抛错');
|
|
593
|
+
}
|
|
594
|
+
const listeners = [];
|
|
595
|
+
const ctxOn = {
|
|
596
|
+
on: (_e, fn)=>{
|
|
597
|
+
listeners.push(fn);
|
|
598
|
+
}
|
|
599
|
+
};
|
|
600
|
+
if (installModelOverride(ctxOn, {
|
|
601
|
+
GOTRY_LLM_MODEL: 'MiniMax-M2'
|
|
602
|
+
}) !== true || listeners.length !== 1) {
|
|
603
|
+
throw new Error('FAIL: 设定 GOTRY_LLM_MODEL 后应挂恰好一条 agent/request 覆盖');
|
|
604
|
+
}
|
|
605
|
+
const inner = async ()=>({
|
|
606
|
+
provider: 'deepseek-official',
|
|
607
|
+
model: 'glm-5.3-flash',
|
|
608
|
+
reasoningEffort: 'high',
|
|
609
|
+
maxTokens: 4096
|
|
610
|
+
});
|
|
611
|
+
const overridden = await listeners[0](null, inner);
|
|
612
|
+
if (overridden.model !== 'MiniMax-M2' || overridden.provider !== 'deepseek-official' || 'reasoningEffort' in overridden || overridden.maxTokens !== 4096) {
|
|
613
|
+
throw new Error(`FAIL: 覆盖结果不符预期:${JSON.stringify(overridden)}`);
|
|
614
|
+
}
|
|
615
|
+
console.log('model override: 未设不挂/无总线不抛/设定后压过用户层选择(glm-5.3-flash→MiniMax-M2)且清继承 effort');
|
|
616
|
+
}
|
|
571
617
|
rmSync(smokeRoot, {
|
|
572
618
|
recursive: true,
|
|
573
619
|
force: true
|
|
@@ -581,4 +627,4 @@ main().catch((e)=>{
|
|
|
581
627
|
});
|
|
582
628
|
|
|
583
629
|
|
|
584
|
-
//# sourceURL
|
|
630
|
+
//# sourceURL=ts/scripts/smoke.ts
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
const modulePath = '../capabilities/session/static-flight-golden.js';
|
|
6
|
+
const provider = await import(modulePath).catch(()=>({}));
|
|
7
|
+
assert.equal(typeof provider.parseGoldenSource, 'function', '缺少 parseGoldenSource 时 CLI 会把未知 vendor 静默当成 manual');
|
|
8
|
+
const parseGoldenSource = provider.parseGoldenSource;
|
|
9
|
+
assert.equal(parseGoldenSource([
|
|
10
|
+
'--golden=static'
|
|
11
|
+
]), 'static');
|
|
12
|
+
assert.equal(parseGoldenSource([]), 'manual');
|
|
13
|
+
assert.throws(()=>parseGoldenSource([
|
|
14
|
+
'--golden=ctrip-open'
|
|
15
|
+
]), /不支持的 golden vendor: ctrip-open/, '未知 vendor 必须 fail-closed,不能静默回退 manual');
|
|
16
|
+
assert.equal(typeof provider.loadStaticFlightSnapshot, 'function', 'static vendor 必须从有 provenance 的版本化快照加载,不能复用 manual 并改标签');
|
|
17
|
+
const snapshot = provider.loadStaticFlightSnapshot();
|
|
18
|
+
assert.equal(snapshot.schema_version, 'sf-static-routes.v1');
|
|
19
|
+
assert.deepEqual(snapshot.source, {
|
|
20
|
+
name: 'OpenFlights routes.dat',
|
|
21
|
+
url: 'https://raw.githubusercontent.com/jpatokal/openflights/4b969f8e91eb800c45f0e0e2355a0fbb93de27e4/data/routes.dat',
|
|
22
|
+
revision: '4b969f8e91eb800c45f0e0e2355a0fbb93de27e4',
|
|
23
|
+
license: 'ODbL-1.0',
|
|
24
|
+
retrieved_at: '2026-08-30',
|
|
25
|
+
limitations: [
|
|
26
|
+
'route/carrier coverage only',
|
|
27
|
+
'no schedule',
|
|
28
|
+
'no price',
|
|
29
|
+
'no availability'
|
|
30
|
+
]
|
|
31
|
+
});
|
|
32
|
+
assert.deepEqual(snapshot.routes.map((route)=>route.query_id), [
|
|
33
|
+
'sf-01',
|
|
34
|
+
'sf-02',
|
|
35
|
+
'sf-03',
|
|
36
|
+
'sf-04',
|
|
37
|
+
'sf-05',
|
|
38
|
+
'sf-06',
|
|
39
|
+
'sf-07',
|
|
40
|
+
'sf-08'
|
|
41
|
+
], '静态快照必须逐条覆盖本批 8 query,不能靠全量 manual fallback 蒙混');
|
|
42
|
+
for (const route of snapshot.routes){
|
|
43
|
+
assert.ok(route.legs.length >= 1, `${route.query_id} 必须至少有一个静态 OD leg`);
|
|
44
|
+
for (const leg of route.legs){
|
|
45
|
+
assert.match(leg.from_iata, /^[A-Z]{3}$/);
|
|
46
|
+
assert.match(leg.to_iata, /^[A-Z]{3}$/);
|
|
47
|
+
assert.ok(leg.carrier_codes.length >= 1);
|
|
48
|
+
}
|
|
49
|
+
assert.equal('departure_at' in route, false, 'OpenFlights 静态包不得伪造班期时刻');
|
|
50
|
+
assert.equal('price' in route, false, 'OpenFlights 静态包不得伪造价格');
|
|
51
|
+
assert.equal('availability' in route, false, 'OpenFlights 静态包不得伪造库存');
|
|
52
|
+
}
|
|
53
|
+
assert.equal(typeof provider.resolveStaticGolden, 'function', '缺少 static→comparable record 解译时 --golden=static 仍不可执行');
|
|
54
|
+
const manualRecord = {
|
|
55
|
+
query_id: 'sf-02',
|
|
56
|
+
route_segments: [
|
|
57
|
+
{
|
|
58
|
+
from: '北京',
|
|
59
|
+
to: '大理',
|
|
60
|
+
departure_at: '2026-10-02T14:00:00+08:00',
|
|
61
|
+
arrival_at: '2026-10-02T17:00:00+08:00',
|
|
62
|
+
transport_number: 'CA1441'
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
journey_type: 'direct',
|
|
66
|
+
currency: 'CNY',
|
|
67
|
+
price: 2650,
|
|
68
|
+
source: 'manual-golden',
|
|
69
|
+
fetched_at: '2026-08-30T12:00:00.000Z',
|
|
70
|
+
verdict: 'hit',
|
|
71
|
+
latency_ms: 0,
|
|
72
|
+
read_guard_blocked: 0
|
|
73
|
+
};
|
|
74
|
+
const staticResolution = provider.resolveStaticGolden({
|
|
75
|
+
query: {
|
|
76
|
+
id: 'sf-02',
|
|
77
|
+
from: '北京',
|
|
78
|
+
to: '大理',
|
|
79
|
+
date: '2026-10-02'
|
|
80
|
+
},
|
|
81
|
+
manualRecord,
|
|
82
|
+
snapshot
|
|
83
|
+
});
|
|
84
|
+
assert.equal(staticResolution.requested_source, 'static');
|
|
85
|
+
assert.equal(staticResolution.effective_source, 'static-openflights+manual-band');
|
|
86
|
+
assert.equal(staticResolution.fallback_reason, undefined);
|
|
87
|
+
assert.equal(staticResolution.record.source, 'static-openflights+manual-band');
|
|
88
|
+
assert.equal(staticResolution.record.journey_type, 'transfer');
|
|
89
|
+
assert.equal(staticResolution.record.route_segments.length, 2);
|
|
90
|
+
assert.deepEqual(staticResolution.record.route_segments.map((segment)=>[
|
|
91
|
+
segment.from,
|
|
92
|
+
segment.to,
|
|
93
|
+
segment.transport_number
|
|
94
|
+
]), [
|
|
95
|
+
[
|
|
96
|
+
'北京',
|
|
97
|
+
'KMG',
|
|
98
|
+
'8L-STATIC'
|
|
99
|
+
],
|
|
100
|
+
[
|
|
101
|
+
'KMG',
|
|
102
|
+
'大理',
|
|
103
|
+
'8L-STATIC'
|
|
104
|
+
]
|
|
105
|
+
]);
|
|
106
|
+
assert.equal(staticResolution.record.route_segments[0]?.departure_at, '2026-10-02T14:00:00+08:00');
|
|
107
|
+
assert.equal(staticResolution.record.route_segments[0]?.arrival_at, '2026-10-02T15:00:00+08:00');
|
|
108
|
+
assert.equal(staticResolution.record.route_segments[1]?.departure_at, '2026-10-02T16:00:00+08:00');
|
|
109
|
+
assert.equal(staticResolution.record.route_segments[1]?.arrival_at, '2026-10-02T17:00:00+08:00');
|
|
110
|
+
assert.equal(staticResolution.record.price, 2650);
|
|
111
|
+
assert.deepEqual(staticResolution.estimated_fields, [
|
|
112
|
+
'route_segments[].departure_at',
|
|
113
|
+
'route_segments[].arrival_at',
|
|
114
|
+
'route_segments[].transport_number',
|
|
115
|
+
'price'
|
|
116
|
+
]);
|
|
117
|
+
assert.deepEqual(staticResolution.provenance, {
|
|
118
|
+
route_source: snapshot.source.url,
|
|
119
|
+
route_revision: '4b969f8e91eb800c45f0e0e2355a0fbb93de27e4',
|
|
120
|
+
route_license: 'ODbL-1.0',
|
|
121
|
+
band_source: 'sf-golden-manifest.json'
|
|
122
|
+
});
|
|
123
|
+
const expectedStaticCoverage = [
|
|
124
|
+
{
|
|
125
|
+
id: 'sf-01',
|
|
126
|
+
from: '上海',
|
|
127
|
+
to: '丽江',
|
|
128
|
+
date: '2026-10-01',
|
|
129
|
+
transport: [
|
|
130
|
+
'MU-STATIC'
|
|
131
|
+
]
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
id: 'sf-02',
|
|
135
|
+
from: '北京',
|
|
136
|
+
to: '大理',
|
|
137
|
+
date: '2026-10-02',
|
|
138
|
+
transport: [
|
|
139
|
+
'8L-STATIC',
|
|
140
|
+
'8L-STATIC'
|
|
141
|
+
]
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
id: 'sf-03',
|
|
145
|
+
from: '上海',
|
|
146
|
+
to: '三亚',
|
|
147
|
+
date: '2026-11-11',
|
|
148
|
+
transport: [
|
|
149
|
+
'9C-STATIC'
|
|
150
|
+
]
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
id: 'sf-04',
|
|
154
|
+
from: '广州',
|
|
155
|
+
to: '昆明',
|
|
156
|
+
date: '2026-12-20',
|
|
157
|
+
transport: [
|
|
158
|
+
'CA-STATIC'
|
|
159
|
+
]
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
id: 'sf-05',
|
|
163
|
+
from: '深圳',
|
|
164
|
+
to: '成都',
|
|
165
|
+
date: '2026-10-05',
|
|
166
|
+
transport: [
|
|
167
|
+
'3U-STATIC'
|
|
168
|
+
]
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
id: 'sf-06',
|
|
172
|
+
from: '杭州',
|
|
173
|
+
to: '厦门',
|
|
174
|
+
date: '2026-10-06',
|
|
175
|
+
transport: [
|
|
176
|
+
'CA-STATIC'
|
|
177
|
+
]
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
id: 'sf-07',
|
|
181
|
+
from: '西安',
|
|
182
|
+
to: '桂林',
|
|
183
|
+
date: '2026-10-07',
|
|
184
|
+
transport: [
|
|
185
|
+
'CA-STATIC'
|
|
186
|
+
]
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
id: 'sf-08',
|
|
190
|
+
from: '重庆',
|
|
191
|
+
to: '贵阳',
|
|
192
|
+
date: '2026-10-08',
|
|
193
|
+
transport: [
|
|
194
|
+
'CA-STATIC'
|
|
195
|
+
]
|
|
196
|
+
}
|
|
197
|
+
];
|
|
198
|
+
for (const expected of expectedStaticCoverage){
|
|
199
|
+
const record = {
|
|
200
|
+
...manualRecord,
|
|
201
|
+
query_id: expected.id,
|
|
202
|
+
route_segments: [
|
|
203
|
+
{
|
|
204
|
+
...manualRecord.route_segments[0],
|
|
205
|
+
from: expected.from,
|
|
206
|
+
to: expected.to,
|
|
207
|
+
departure_at: `${expected.date}T06:00:00+08:00`,
|
|
208
|
+
arrival_at: `${expected.date}T12:00:00+08:00`
|
|
209
|
+
}
|
|
210
|
+
]
|
|
211
|
+
};
|
|
212
|
+
const resolution = provider.resolveStaticGolden({
|
|
213
|
+
query: {
|
|
214
|
+
id: expected.id,
|
|
215
|
+
from: expected.from,
|
|
216
|
+
to: expected.to,
|
|
217
|
+
date: expected.date
|
|
218
|
+
},
|
|
219
|
+
manualRecord: record,
|
|
220
|
+
snapshot
|
|
221
|
+
});
|
|
222
|
+
assert.equal(resolution.effective_source, 'static-openflights+manual-band', `${expected.id} 不得全量回退 manual`);
|
|
223
|
+
assert.equal(resolution.fallback_reason, undefined);
|
|
224
|
+
assert.equal(resolution.record.route_segments.length, expected.transport.length);
|
|
225
|
+
assert.equal(resolution.record.route_segments[0]?.from, expected.from);
|
|
226
|
+
assert.equal(resolution.record.route_segments.at(-1)?.to, expected.to);
|
|
227
|
+
assert.deepEqual(resolution.record.route_segments.map((segment)=>segment.transport_number), expected.transport, `${expected.id} 运行时首选 carrier 必须来自已核对的 pinned route row`);
|
|
228
|
+
for (const segment of resolution.record.route_segments){
|
|
229
|
+
assert.match(segment.transport_number, /^[A-Z0-9]{2}-STATIC$/);
|
|
230
|
+
assert.ok(Number.isFinite(Date.parse(segment.departure_at)));
|
|
231
|
+
assert.ok(Number.isFinite(Date.parse(segment.arrival_at)));
|
|
232
|
+
assert.ok(Date.parse(segment.arrival_at) > Date.parse(segment.departure_at));
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
const warnings = [];
|
|
236
|
+
const fallbackRecord = {
|
|
237
|
+
...manualRecord,
|
|
238
|
+
query_id: 'sf-99'
|
|
239
|
+
};
|
|
240
|
+
const fallbackResolution = provider.resolveStaticGolden({
|
|
241
|
+
query: {
|
|
242
|
+
id: 'sf-99',
|
|
243
|
+
from: '北京',
|
|
244
|
+
to: '大理',
|
|
245
|
+
date: '2026-10-02'
|
|
246
|
+
},
|
|
247
|
+
manualRecord: fallbackRecord,
|
|
248
|
+
snapshot,
|
|
249
|
+
warn: (message)=>warnings.push(message)
|
|
250
|
+
});
|
|
251
|
+
assert.equal(fallbackResolution.effective_source, 'manual-golden');
|
|
252
|
+
assert.equal(fallbackResolution.record, fallbackRecord, 'fallback 必须原样使用 manual record');
|
|
253
|
+
assert.equal(fallbackResolution.fallback_reason, 'static route missing for sf-99');
|
|
254
|
+
assert.deepEqual(warnings, [
|
|
255
|
+
'[sf-live-benchmark] static vendor failed for sf-99: static route missing for sf-99; fallback=manual-golden'
|
|
256
|
+
]);
|
|
257
|
+
const snapshotWarnings = [];
|
|
258
|
+
const unavailableResolution = provider.resolveStaticGolden({
|
|
259
|
+
query: {
|
|
260
|
+
id: 'sf-02',
|
|
261
|
+
from: '北京',
|
|
262
|
+
to: '大理',
|
|
263
|
+
date: '2026-10-02'
|
|
264
|
+
},
|
|
265
|
+
manualRecord,
|
|
266
|
+
snapshotError: 'invalid static snapshot schema_version',
|
|
267
|
+
warn: (message)=>snapshotWarnings.push(message)
|
|
268
|
+
});
|
|
269
|
+
assert.equal(unavailableResolution.effective_source, 'manual-golden');
|
|
270
|
+
assert.equal(unavailableResolution.fallback_reason, 'static snapshot unavailable: invalid static snapshot schema_version');
|
|
271
|
+
assert.deepEqual(snapshotWarnings, [
|
|
272
|
+
'[sf-live-benchmark] static vendor failed for sf-02: static snapshot unavailable: invalid static snapshot schema_version; fallback=manual-golden'
|
|
273
|
+
]);
|
|
274
|
+
const malformedRoot = mkdtempSync(join(tmpdir(), 'gotry-static-golden-'));
|
|
275
|
+
try {
|
|
276
|
+
const malformedPath = join(malformedRoot, 'malformed.json');
|
|
277
|
+
writeFileSync(malformedPath, JSON.stringify({
|
|
278
|
+
schema_version: 'sf-static-routes.v0',
|
|
279
|
+
source: {},
|
|
280
|
+
routes: []
|
|
281
|
+
}));
|
|
282
|
+
assert.throws(()=>provider.loadStaticFlightSnapshot(malformedPath), /invalid static snapshot schema_version: sf-static-routes.v0/, '未知 schema 不得被类型断言伪装成有效 static vendor');
|
|
283
|
+
const malformedRoutesPath = join(malformedRoot, 'malformed-routes.json');
|
|
284
|
+
writeFileSync(malformedRoutesPath, JSON.stringify({
|
|
285
|
+
schema_version: 'sf-static-routes.v1',
|
|
286
|
+
source: snapshot.source,
|
|
287
|
+
routes: null
|
|
288
|
+
}));
|
|
289
|
+
assert.throws(()=>provider.loadStaticFlightSnapshot(malformedRoutesPath), /invalid static snapshot routes/, 'schema 名正确但 routes 损坏时也必须由 loader 截获,runner 才能降级 manual');
|
|
290
|
+
} finally{
|
|
291
|
+
rmSync(malformedRoot, {
|
|
292
|
+
recursive: true,
|
|
293
|
+
force: true
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
console.log('STATIC GOLDEN TESTS: parser + snapshot + resolve/fallback contract OK');
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
//# sourceURL=ts/scripts/static-golden-tests.ts
|