@danceiny/gotry 0.0.1-rc.15 → 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 +51 -13
- package/README.zh-CN.md +26 -12
- package/bin/gotry-booking-copilot.js +53 -0
- package/bin/gotry-bootstrap.js +357 -8
- 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 +15 -1
- package/data/airline-airports.json +39 -0
- 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 +293 -0
- package/dist/capabilities/fact-log.js +41 -0
- package/dist/capabilities/flyai.js +20 -6
- package/dist/capabilities/hbcli.js +43 -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 +90 -0
- 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 +2 -1
- package/dist/capabilities/session/extension-bridge.js +358 -0
- package/dist/capabilities/session/extension-channel.js +93 -0
- 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 +216 -0
- 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 +147 -0
- package/dist/capabilities/session-consent.js +1 -1
- package/dist/capabilities/session-login.js +83 -1
- package/dist/capabilities/session-search.js +111 -2
- 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 +59 -3
- package/dist/scripts/build-changelog.js +279 -0
- package/dist/scripts/changelog-tests.js +165 -0
- 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 +474 -0
- 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 +573 -0
- package/dist/scripts/fact-gate-tests.js +318 -0
- package/dist/scripts/flyai-tests.js +1 -1
- package/dist/scripts/hbcli-e2e-tests.js +180 -0
- package/dist/scripts/hbcli-tests.js +1 -1
- package/dist/scripts/health-watch-cli.js +51 -0
- 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 +67 -4
- package/dist/scripts/nightly-evidence.js +59 -3
- package/dist/scripts/nudge-digest.js +1 -1
- package/dist/scripts/onboarding-tests.js +186 -0
- 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 +441 -0
- package/dist/scripts/price-drift-watch.js +491 -0
- 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 +154 -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 +310 -0
- 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 +349 -0
- 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 +234 -60
- 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 +14 -7
- 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 +50 -0
- package/extension/background.js +160 -0
- package/extension/content-bridge.js +41 -0
- package/extension/content-main.js +62 -0
- package/extension/manifest.json +32 -0
- package/package.json +291 -12
- package/schemas/booking.surface.v1.schema.json +927 -0
- package/schemas/booking.surface.v2.schema.json +61 -0
- package/ts/capabilities/fact-log.ts +54 -0
- package/ts/capabilities/flyai.ts +16 -3
- package/ts/capabilities/hbcli.ts +46 -0
- package/ts/capabilities/session/benchmark.ts +4 -1
- package/ts/capabilities/session/extension-bridge.ts +377 -0
- package/ts/capabilities/session/extension-channel.ts +95 -0
- 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 +257 -0
- package/ts/capabilities/session/static-flight-golden.ts +209 -0
- package/ts/capabilities/session/wizard.ts +140 -0
- package/ts/capabilities/session-login.ts +63 -2
- package/ts/capabilities/session-search.ts +105 -3
- package/ts/capabilities/weather.ts +141 -52
- package/ts/package.json +3 -3
- package/ts/src/artifact-gate.ts +365 -0
- 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/bookable-facts.ts +557 -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 +161 -14
- package/ts/src/state-ledger.ts +1 -0
- package/ts/src/tool-budget.ts +165 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { copyFileSync, existsSync, mkdirSync, readdirSync, statSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
const DEFAULT_SOURCE_DIR_CANDIDATES = [
|
|
5
|
+
join(process.cwd(), 'extension'),
|
|
6
|
+
join(process.cwd(), 'dist', 'extension'),
|
|
7
|
+
join(process.cwd(), 'ts', '..', 'extension')
|
|
8
|
+
];
|
|
9
|
+
function resolveExtensionSourceDir() {
|
|
10
|
+
for (const candidate of DEFAULT_SOURCE_DIR_CANDIDATES){
|
|
11
|
+
if (existsSync(join(candidate, 'manifest.json'))) return candidate;
|
|
12
|
+
}
|
|
13
|
+
return DEFAULT_SOURCE_DIR_CANDIDATES[0];
|
|
14
|
+
}
|
|
15
|
+
export function defaultExtensionDir() {
|
|
16
|
+
return join(homedir(), '.gotry', 'extension');
|
|
17
|
+
}
|
|
18
|
+
function ensureExtensionFiles(source, target, dryRun) {
|
|
19
|
+
if (dryRun) return {
|
|
20
|
+
step: 'ensure-extension-files',
|
|
21
|
+
status: 'skip',
|
|
22
|
+
summary: '[dry-run] skip 扩展落位'
|
|
23
|
+
};
|
|
24
|
+
try {
|
|
25
|
+
if (!existsSync(source) || !existsSync(join(source, 'manifest.json'))) {
|
|
26
|
+
return {
|
|
27
|
+
step: 'ensure-extension-files',
|
|
28
|
+
status: 'fail',
|
|
29
|
+
summary: `源扩展目录缺失 manifest.json: ${source}(先跑 npx gotry setup 落位)`
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
mkdirSync(target, {
|
|
33
|
+
recursive: true
|
|
34
|
+
});
|
|
35
|
+
const required = [
|
|
36
|
+
'manifest.json',
|
|
37
|
+
'background.js',
|
|
38
|
+
'content-main.js',
|
|
39
|
+
'content-bridge.js'
|
|
40
|
+
];
|
|
41
|
+
for (const f of required){
|
|
42
|
+
const src = join(source, f);
|
|
43
|
+
if (!existsSync(src)) return {
|
|
44
|
+
step: 'ensure-extension-files',
|
|
45
|
+
status: 'fail',
|
|
46
|
+
summary: `源扩展缺 ${f}(重新 npm install 或 gotry setup)`
|
|
47
|
+
};
|
|
48
|
+
copyFileSync(src, join(target, f));
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
step: 'ensure-extension-files',
|
|
52
|
+
status: 'ok',
|
|
53
|
+
summary: `扩展已落位 ${target}(manifest+3 文件)`
|
|
54
|
+
};
|
|
55
|
+
} catch (e) {
|
|
56
|
+
return {
|
|
57
|
+
step: 'ensure-extension-files',
|
|
58
|
+
status: 'fail',
|
|
59
|
+
summary: `扩展落位失败: ${e instanceof Error ? e.message.slice(0, 120) : String(e)}`
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function watchExtensionReady(dryRun, sourceDir, extensionDir) {
|
|
64
|
+
if (dryRun) return {
|
|
65
|
+
step: 'watch-extension-ready',
|
|
66
|
+
status: 'skip',
|
|
67
|
+
summary: '[dry-run] skip health-watch precheck'
|
|
68
|
+
};
|
|
69
|
+
if (!existsSync(extensionDir) || !existsSync(join(extensionDir, 'manifest.json'))) {
|
|
70
|
+
return {
|
|
71
|
+
step: 'watch-extension-ready',
|
|
72
|
+
status: 'fail',
|
|
73
|
+
summary: `落位缺失 manifest.json:${extensionDir}`
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
const srcStat = statSync(sourceDir);
|
|
78
|
+
const dstStat = statSync(extensionDir);
|
|
79
|
+
if (srcStat.mtimeMs > dstStat.mtimeMs) {
|
|
80
|
+
return {
|
|
81
|
+
step: 'watch-extension-ready',
|
|
82
|
+
status: 'fail',
|
|
83
|
+
summary: `扩展文件可能过期(源比落位新);重跑 npx gotry setup`
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const manifest = JSON.parse(await (await import('node:fs/promises')).readFile(join(extensionDir, 'manifest.json'), 'utf8'));
|
|
87
|
+
if (typeof manifest.key !== 'string' || manifest.key.length < 100) {
|
|
88
|
+
return {
|
|
89
|
+
step: 'watch-extension-ready',
|
|
90
|
+
status: 'fail',
|
|
91
|
+
summary: 'manifest.key 缺失或过短,扩展 ID 不能稳定'
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
} catch (e) {
|
|
95
|
+
return {
|
|
96
|
+
step: 'watch-extension-ready',
|
|
97
|
+
status: 'fail',
|
|
98
|
+
summary: `静态预检失败: ${e instanceof Error ? e.message.slice(0, 120) : String(e)}`
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
step: 'watch-extension-ready',
|
|
103
|
+
status: 'ok',
|
|
104
|
+
summary: '扩展文件就绪(manifest.key 校验通过,后台轮询就绪态由 health-watch 接管)'
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
export async function runOnboardingWizard(opts = {}) {
|
|
108
|
+
const dryRun = opts.dryRun ?? false;
|
|
109
|
+
const extensionDir = opts.extensionDir ?? defaultExtensionDir();
|
|
110
|
+
const sourceDir = opts.sourceDir ?? resolveExtensionSourceDir();
|
|
111
|
+
const steps = [];
|
|
112
|
+
steps.push(ensureExtensionFiles(sourceDir, extensionDir, dryRun));
|
|
113
|
+
steps.push(await watchExtensionReady(dryRun, sourceDir, extensionDir));
|
|
114
|
+
const ok = steps.every((s)=>s.status !== 'fail');
|
|
115
|
+
return {
|
|
116
|
+
ok,
|
|
117
|
+
steps,
|
|
118
|
+
extensionDir
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
export function printWizardResult(result, destination = process.stdout) {
|
|
122
|
+
const tag = (s)=>{
|
|
123
|
+
if (s.status === 'ok') return '✅';
|
|
124
|
+
if (s.status === 'skip') return '⏭ ';
|
|
125
|
+
return '❌';
|
|
126
|
+
};
|
|
127
|
+
for (const s of result.steps){
|
|
128
|
+
destination.write(`${tag(s)} ${s.step}: ${s.summary}\n`);
|
|
129
|
+
}
|
|
130
|
+
destination.write(`extensionDir=${result.extensionDir}; overall=${result.ok ? 'ok' : 'has-failures'}\n`);
|
|
131
|
+
}
|
|
132
|
+
export function describeExtensionDir(extensionDir) {
|
|
133
|
+
if (!existsSync(extensionDir)) return {
|
|
134
|
+
exists: false,
|
|
135
|
+
fileCount: 0,
|
|
136
|
+
hasManifest: false
|
|
137
|
+
};
|
|
138
|
+
const files = readdirSync(extensionDir);
|
|
139
|
+
return {
|
|
140
|
+
exists: true,
|
|
141
|
+
fileCount: files.length,
|
|
142
|
+
hasManifest: files.includes('manifest.json')
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
//# sourceURL=ts/capabilities/session/wizard.ts
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { openSession } from './session/transport.js';
|
|
2
|
+
import { extensionCookieNames, extensionOpenLogin, classifyBridgeFailure } from './session/extension-channel.js';
|
|
3
|
+
import { EXTENSION_STORE_URL } from './session/extension-bridge.js';
|
|
4
|
+
import { resolveTransportMode } from './session-search.js';
|
|
2
5
|
export const LOGIN_TARGETS = {
|
|
3
6
|
'ctrip-flight': {
|
|
4
7
|
domain: 'ctrip.com',
|
|
@@ -47,6 +50,9 @@ export async function sessionLogin(q = {}) {
|
|
|
47
50
|
if (!target) {
|
|
48
51
|
return err(site, 'error', `未知站点 ${site}(可选 ${Object.keys(LOGIN_TARGETS).join('/')})`, started, ts);
|
|
49
52
|
}
|
|
53
|
+
if (resolveTransportMode() === 'extension') {
|
|
54
|
+
return sessionLoginViaExtension(site, target, q, started, ts);
|
|
55
|
+
}
|
|
50
56
|
const t = await openSession({
|
|
51
57
|
mode: 'cdp',
|
|
52
58
|
guard: false
|
|
@@ -114,6 +120,82 @@ export async function sessionLogin(q = {}) {
|
|
|
114
120
|
return err(site, 'error', e instanceof Error ? e.message : String(e), started, ts);
|
|
115
121
|
}
|
|
116
122
|
}
|
|
123
|
+
async function sessionLoginViaExtension(site, target, q, started, ts) {
|
|
124
|
+
const evidenceTag = `[会话:${site}-login@${ts}]`;
|
|
125
|
+
const quick = (verdict, error)=>{
|
|
126
|
+
const base = {
|
|
127
|
+
ok: false,
|
|
128
|
+
via: 'session-login-error',
|
|
129
|
+
evidence: `[会话:login-error@${ts}] ${error.slice(0, 200)}`,
|
|
130
|
+
latencyMs: Date.now() - started,
|
|
131
|
+
verdict,
|
|
132
|
+
site,
|
|
133
|
+
error: error.slice(0, 400)
|
|
134
|
+
};
|
|
135
|
+
if (verdict === 'needs-extension') base.installUrl = EXTENSION_STORE_URL;
|
|
136
|
+
if (verdict === 'needs-extension') base.installAction = 'add-to-chrome';
|
|
137
|
+
return base;
|
|
138
|
+
};
|
|
139
|
+
const pre = await extensionCookieNames({
|
|
140
|
+
site,
|
|
141
|
+
domain: target.domain,
|
|
142
|
+
ticketNames: target.names,
|
|
143
|
+
timeoutMs: 8_000
|
|
144
|
+
});
|
|
145
|
+
if (!pre.ok) return quick(classifyBridgeFailure(pre.kind) === 'needs-extension' ? 'needs-extension' : 'error', pre.summary);
|
|
146
|
+
if (pre.tickets.length > 0) {
|
|
147
|
+
return {
|
|
148
|
+
ok: true,
|
|
149
|
+
via: 'session-login',
|
|
150
|
+
latencyMs: Date.now() - started,
|
|
151
|
+
verdict: 'logged-in',
|
|
152
|
+
site,
|
|
153
|
+
tickets: pre.tickets,
|
|
154
|
+
evidence: `${evidenceTag} 自动检测:票据 cookie 已在(先前登录已生效)——[${pre.tickets.join(', ')}](只读名字,0 网页交互,零弹窗)`
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
const opened = await extensionOpenLogin({
|
|
158
|
+
site,
|
|
159
|
+
url: target.entryUrl,
|
|
160
|
+
timeoutMs: 15_000
|
|
161
|
+
});
|
|
162
|
+
if (!opened.ok) return quick(classifyBridgeFailure(opened.kind) === 'needs-extension' ? 'needs-extension' : 'error', opened.summary);
|
|
163
|
+
const waitMs = Math.min(Math.max(q.waitMs ?? 90_000, 0), 300_000);
|
|
164
|
+
const pollMs = Math.min(Math.max(q.pollMs ?? 3_000, 500), 10_000);
|
|
165
|
+
const deadline = Date.now() + waitMs;
|
|
166
|
+
let tickets = [];
|
|
167
|
+
while(Date.now() < deadline){
|
|
168
|
+
await new Promise((resolve)=>setTimeout(resolve, pollMs));
|
|
169
|
+
const poll = await extensionCookieNames({
|
|
170
|
+
site,
|
|
171
|
+
domain: target.domain,
|
|
172
|
+
ticketNames: target.names,
|
|
173
|
+
timeoutMs: 8_000
|
|
174
|
+
});
|
|
175
|
+
if (poll.ok) tickets = poll.tickets;
|
|
176
|
+
if (tickets.length > 0) break;
|
|
177
|
+
}
|
|
178
|
+
if (tickets.length > 0) {
|
|
179
|
+
return {
|
|
180
|
+
ok: true,
|
|
181
|
+
via: 'session-login',
|
|
182
|
+
latencyMs: Date.now() - started,
|
|
183
|
+
verdict: 'logged-in',
|
|
184
|
+
site,
|
|
185
|
+
tickets,
|
|
186
|
+
evidence: `${evidenceTag} 票据 cookie 已检出 [${tickets.join(', ')}](只读名字;登录在你自己的浏览器里完成,gotry 全程未接触任何密码/验证码/cookie 值)`
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
ok: true,
|
|
191
|
+
via: 'session-login',
|
|
192
|
+
latencyMs: Date.now() - started,
|
|
193
|
+
verdict: 'pending',
|
|
194
|
+
site,
|
|
195
|
+
tickets: [],
|
|
196
|
+
evidence: `${evidenceTag} 登录入口已在你的 Chrome 置前打开(${target.label});在标签页里正常登录完成后再说一声「继续查」即可——gotry 只检查"是否已登录",永不收集你的账号信息`
|
|
197
|
+
};
|
|
198
|
+
}
|
|
117
199
|
|
|
118
200
|
|
|
119
|
-
//# sourceURL
|
|
201
|
+
//# sourceURL=ts/capabilities/session-login.ts
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { openSession } from './session/transport.js';
|
|
2
|
+
import { extensionCookieNames, extensionSearchJob, classifyBridgeFailure } from './session/extension-channel.js';
|
|
3
|
+
import { appendFileSync, mkdirSync } from 'node:fs';
|
|
4
|
+
import { dirname } from 'node:path';
|
|
2
5
|
import { buildEntryUrl, NETWORK_HINTS, parseBatchSearch, LOGIN_COOKIE_NAMES, SITE_DOMAIN } from './session/adapters/ctrip-flight.js';
|
|
6
|
+
import { EXTENSION_STORE_URL } from './session/extension-bridge.js';
|
|
3
7
|
const MIN_INTERVAL_MS = 30_000;
|
|
4
8
|
const lastCallAt = new Map();
|
|
5
9
|
export function __resetRateLimiterForTest() {
|
|
@@ -9,6 +13,41 @@ const CHALLENGE_RE = /验证|滑块|captcha|verify/i;
|
|
|
9
13
|
export function classifyTransportFailure(summary, cdpMode) {
|
|
10
14
|
return cdpMode && /日常 Chrome 未开调试端口|cdp attach 失败/.test(summary) ? 'needs-attach' : 'error';
|
|
11
15
|
}
|
|
16
|
+
export function resolveTransportMode(profileDir) {
|
|
17
|
+
if (profileDir !== undefined) return 'persistent';
|
|
18
|
+
return (process.env.GOTRY_SESSION_TRANSPORT ?? '').trim().toLowerCase() === 'cdp' ? 'cdp' : 'extension';
|
|
19
|
+
}
|
|
20
|
+
export function sessionLiveEnabled(env = process.env) {
|
|
21
|
+
return env.GOTRY_SESSION_LIVE === '1';
|
|
22
|
+
}
|
|
23
|
+
export function offlineSessionFlightResult() {
|
|
24
|
+
return {
|
|
25
|
+
ok: false,
|
|
26
|
+
via: 'session-ctrip-flight-error',
|
|
27
|
+
evidence: '[会话:ctrip-flight@offline] GOTRY_SESSION_LIVE!=1; live transport not invoked',
|
|
28
|
+
latencyMs: 0,
|
|
29
|
+
verdict: 'error',
|
|
30
|
+
error: 'GOTRY_SESSION_LIVE=1 required for live session transport'
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export async function gatedSessionFlightSearch(q, search = sessionFlightSearch, env = process.env) {
|
|
34
|
+
if (!sessionLiveEnabled(env)) return offlineSessionFlightResult();
|
|
35
|
+
return search(q);
|
|
36
|
+
}
|
|
37
|
+
export function appendExtensionAudit(auditPath, entry) {
|
|
38
|
+
if (!auditPath) return;
|
|
39
|
+
try {
|
|
40
|
+
const record = {
|
|
41
|
+
ts: new Date().toISOString(),
|
|
42
|
+
...entry,
|
|
43
|
+
url: entry.url.slice(0, 400)
|
|
44
|
+
};
|
|
45
|
+
mkdirSync(dirname(auditPath), {
|
|
46
|
+
recursive: true
|
|
47
|
+
});
|
|
48
|
+
appendFileSync(auditPath, JSON.stringify(record) + '\n');
|
|
49
|
+
} catch {}
|
|
50
|
+
}
|
|
12
51
|
export async function sessionFlightSearch(q) {
|
|
13
52
|
const started = Date.now();
|
|
14
53
|
const ts = new Date().toISOString();
|
|
@@ -30,11 +69,81 @@ export async function sessionFlightSearch(q) {
|
|
|
30
69
|
if (!entry.ok || !entry.url) {
|
|
31
70
|
return err('error', `unresolved entry: ${(entry.unresolved ?? []).join('/')} 不在城市码表`);
|
|
32
71
|
}
|
|
72
|
+
const mode = resolveTransportMode(q.profileDir);
|
|
73
|
+
if (mode === 'extension') {
|
|
74
|
+
const login = await extensionCookieNames({
|
|
75
|
+
site,
|
|
76
|
+
domain: SITE_DOMAIN.replace(/^\./, ''),
|
|
77
|
+
ticketNames: LOGIN_COOKIE_NAMES
|
|
78
|
+
});
|
|
79
|
+
if (!login.ok) {
|
|
80
|
+
const verdict = classifyBridgeFailure(login.kind);
|
|
81
|
+
if (verdict === 'needs-extension') {
|
|
82
|
+
return {
|
|
83
|
+
ok: false,
|
|
84
|
+
via: 'session-ctrip-flight-error',
|
|
85
|
+
evidence: '[会话:ctrip-flight-needs-extension@ts]',
|
|
86
|
+
latencyMs: Date.now() - started,
|
|
87
|
+
verdict,
|
|
88
|
+
error: login.summary,
|
|
89
|
+
installUrl: EXTENSION_STORE_URL,
|
|
90
|
+
installAction: 'add-to-chrome'
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
return err(verdict, login.summary);
|
|
94
|
+
}
|
|
95
|
+
if (login.tickets.length === 0 && !q.allowAnonymous) {
|
|
96
|
+
return err('needs-login', '未检出你本人登录态——调用 gotry_session_login 为用户打开携程登录入口(登录在携程官网完成;gotry 永不经手密码/验证码/cookie 值)');
|
|
97
|
+
}
|
|
98
|
+
const r = await extensionSearchJob({
|
|
99
|
+
site,
|
|
100
|
+
url: entry.url,
|
|
101
|
+
timeoutMs: q.timeoutMs
|
|
102
|
+
});
|
|
103
|
+
appendExtensionAudit(q.auditPath, {
|
|
104
|
+
kind: 'extension-session-job',
|
|
105
|
+
site,
|
|
106
|
+
url: entry.url,
|
|
107
|
+
jobId: 'search',
|
|
108
|
+
result: r.ok ? r.timedOut ? 'timeout' : `body ${r.body.length}B title="${r.title.slice(0, 60)}"` : `${r.kind}:${r.summary.slice(0, 120)}`
|
|
109
|
+
});
|
|
110
|
+
if (!r.ok) {
|
|
111
|
+
const verdict = classifyBridgeFailure(r.kind);
|
|
112
|
+
if (verdict === 'needs-extension') {
|
|
113
|
+
return {
|
|
114
|
+
ok: false,
|
|
115
|
+
via: 'session-ctrip-flight-error',
|
|
116
|
+
evidence: '[会话:ctrip-flight-needs-extension@ts]',
|
|
117
|
+
latencyMs: Date.now() - started,
|
|
118
|
+
verdict,
|
|
119
|
+
error: r.summary,
|
|
120
|
+
installUrl: EXTENSION_STORE_URL,
|
|
121
|
+
installAction: 'add-to-chrome'
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
return err(verdict, r.summary);
|
|
125
|
+
}
|
|
126
|
+
const title = r.title;
|
|
127
|
+
const head = r.body.slice(0, 5000);
|
|
128
|
+
if (CHALLENGE_RE.test(title + head)) {
|
|
129
|
+
return err('challenged', `风控/验证码命中(title=${title.slice(0, 60)});按红线不重试不绕过,交还用户`);
|
|
130
|
+
}
|
|
131
|
+
const options = parseBatchSearch(r.body);
|
|
132
|
+
const verdict = options.length > 0 ? 'hit' : 'miss';
|
|
133
|
+
return {
|
|
134
|
+
ok: true,
|
|
135
|
+
via: 'session-ctrip-flight',
|
|
136
|
+
evidence: `[会话:${site}@${ts}] ${options.length} options;transport=extension(被动嗅探,零系统弹窗;扩展零写行为=物理只读)${q.allowAnonymous ? ';anonymous=自检态' : ''}`,
|
|
137
|
+
latencyMs: Date.now() - started,
|
|
138
|
+
verdict,
|
|
139
|
+
options
|
|
140
|
+
};
|
|
141
|
+
}
|
|
33
142
|
const t = await openSession({
|
|
34
143
|
profileDir: q.profileDir,
|
|
35
144
|
headless: q.headless,
|
|
36
145
|
auditPath: q.auditPath,
|
|
37
|
-
mode:
|
|
146
|
+
mode: mode === 'persistent' ? 'persistent' : 'cdp',
|
|
38
147
|
newPage: true
|
|
39
148
|
});
|
|
40
149
|
if (!t.ok) {
|
|
@@ -93,4 +202,4 @@ export async function sessionFlightSearch(q) {
|
|
|
93
202
|
}
|
|
94
203
|
|
|
95
204
|
|
|
96
|
-
//# sourceURL
|
|
205
|
+
//# sourceURL=ts/capabilities/session-search.ts
|