@danceiny/gotry 0.0.1-rc.21 → 0.0.1-rc.24
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 +102 -194
- package/README.zh-CN.md +115 -210
- package/bin/gotry-backend.js +53 -0
- package/bin/gotry-bootstrap.js +466 -35
- package/bin/gotry-inner.js +255 -36
- package/bin/gotry-process-liveness.d.ts +27 -0
- package/bin/gotry-process-liveness.js +97 -0
- package/bin/gotry-runtime-resolution.d.ts +1 -1
- package/bin/gotry-runtime-resolution.js +2 -2
- package/client/client.js +174 -0
- package/cordis.gotry-patch.yml +70 -93
- package/dist/capabilities/agent-reach-deep.js +45 -122
- package/dist/capabilities/agent-reach.js +63 -148
- package/dist/capabilities/anything.js +89 -75
- package/dist/capabilities/artifacts.js +123 -104
- package/dist/capabilities/channel-health.js +65 -45
- package/dist/capabilities/channel-registry.js +108 -87
- package/dist/capabilities/doctor.js +357 -235
- package/dist/capabilities/effect.js +223 -309
- package/dist/capabilities/fact-log.js +28 -14
- package/dist/capabilities/flyai.js +245 -156
- package/dist/capabilities/ground-transfer.js +509 -0
- package/dist/capabilities/hbcli.js +144 -148
- package/dist/capabilities/hotelbyte-transaction.js +194 -0
- package/dist/capabilities/incident-log.js +131 -61
- package/dist/capabilities/model-override.js +30 -10
- package/dist/capabilities/opensky.js +54 -43
- package/dist/capabilities/resilience.js +50 -32
- package/dist/capabilities/session/action-cache.js +50 -44
- package/dist/capabilities/session/adapters/ctrip-flight.js +119 -62
- package/dist/capabilities/session/adapters/ctrip-hotel.js +125 -110
- package/dist/capabilities/session/adapters/dida-portal.js +206 -0
- package/dist/capabilities/session/adapters/meituan-local.js +35 -54
- package/dist/capabilities/session/adapters/rail-12306.js +169 -112
- package/dist/capabilities/session/benchmark.js +85 -149
- package/dist/capabilities/session/extension-bridge.js +320 -259
- package/dist/capabilities/session/extension-channel.js +57 -76
- package/dist/capabilities/session/extension-distribution.js +115 -119
- package/dist/capabilities/session/extract.js +31 -21
- package/dist/capabilities/session/golden-score.js +55 -33
- package/dist/capabilities/session/health-watch.js +146 -154
- package/dist/capabilities/session/read-guard.js +55 -47
- package/dist/capabilities/session/static-flight-golden.js +49 -36
- package/dist/capabilities/session/transport.js +54 -61
- package/dist/capabilities/session/wizard.js +63 -93
- package/dist/capabilities/session-consent.js +143 -47
- package/dist/capabilities/session-login.js +95 -126
- package/dist/capabilities/session-search.js +391 -253
- package/dist/capabilities/sponsor-plugin.js +341 -0
- package/dist/capabilities/visa-policy.js +87 -73
- package/dist/capabilities/weather.js +163 -235
- package/dist/scripts/action-cache-tests.js +24 -59
- package/dist/scripts/agent-planning-turn-deadline-e2e.js +91 -142
- package/dist/scripts/agent-planning-turn-deadline-tests.js +80 -176
- package/dist/scripts/agent-reach-deep-tests.js +30 -40
- package/dist/scripts/agent-reach-tests.js +26 -18
- package/dist/scripts/agent-reach-wrapper-tests.js +46 -50
- package/dist/scripts/anything-tests.js +58 -62
- package/dist/scripts/artifact-client-contract-tests.js +69 -0
- package/dist/scripts/artifacts-capability-tests.js +235 -0
- package/dist/scripts/async-collect.js +26 -15
- package/dist/scripts/benchmark-environment-bridge-e2e.js +287 -684
- package/dist/scripts/benchmark-environment-bridge-tests.js +818 -3123
- package/dist/scripts/booking-copilot-availability-ledger-binding-tests.js +66 -279
- package/dist/scripts/booking-copilot-availability-policy-tests.js +153 -1257
- package/dist/scripts/booking-copilot-bin-proof-tests.js +22 -45
- package/dist/scripts/booking-copilot-crossrepo-fixture-server.js +64 -76
- package/dist/scripts/booking-copilot-dsh-core-proof-tests.js +69 -199
- package/dist/scripts/booking-copilot-dsh-planner-proof-tests.js +393 -759
- package/dist/scripts/booking-copilot-dsh-plugin-proof-tests.js +33 -75
- package/dist/scripts/booking-copilot-event-sequence-concurrency-proof-tests.js +60 -110
- package/dist/scripts/booking-copilot-gap-code-contract-proof-tests.js +28 -66
- package/dist/scripts/booking-copilot-operation-ledger-concurrency-proof-tests.js +72 -271
- package/dist/scripts/booking-copilot-receipt-ledger-concurrency-proof-tests.js +73 -275
- package/dist/scripts/booking-copilot-runtime-proof-tests.js +784 -3398
- package/dist/scripts/booking-copilot-server-proof-tests.js +63 -168
- package/dist/scripts/booking-copilot-startup-proof-tests.js +38 -124
- package/dist/scripts/booking-executor-tests.js +80 -0
- package/dist/scripts/booking-recovery-chain-tests.js +182 -0
- package/dist/scripts/booking-saga-tests.js +61 -123
- package/dist/scripts/booking-surface-contract-proof-tests.js +152 -1167
- package/dist/scripts/bootstrap-tests.js +1383 -128
- package/dist/scripts/build-changelog.js +89 -130
- package/dist/scripts/build-metrics-report.js +135 -143
- package/dist/scripts/changelog-tests.js +35 -82
- package/dist/scripts/channel-probe-tests.js +44 -116
- package/dist/scripts/channel-probe.js +84 -167
- package/dist/scripts/channel-registry-tests.js +97 -185
- package/dist/scripts/companion-tests.js +25 -70
- package/dist/scripts/dida-cookie-probe.js +87 -0
- package/dist/scripts/dida-sw-probe.js +114 -0
- package/dist/scripts/diff-test.js +17 -12
- package/dist/scripts/doctor-tests.js +428 -120
- package/dist/scripts/dsh-artifact-e2e.js +150 -0
- package/dist/scripts/dsh-artifact-web-e2e.js +443 -0
- package/dist/scripts/dsh-http-proxy-sse-proof.js +90 -0
- package/dist/scripts/dsh-runtime-closure-tests.js +110 -153
- package/dist/scripts/dsh-runtime-closure.js +75 -63
- package/dist/scripts/dsh-session-v3-migration-proof.js +106 -0
- package/dist/scripts/dsh-subprocess-local-proof.js +149 -0
- package/dist/scripts/dsh-target-closure-proof.js +178 -0
- package/dist/scripts/effect-tests.js +165 -552
- package/dist/scripts/engine-run.js +1 -3
- package/dist/scripts/engine-tests.js +16 -10
- package/dist/scripts/evaluation-cadence-tests.js +69 -242
- package/dist/scripts/evaluation-contract-tests.js +193 -499
- package/dist/scripts/extension-distribution-cli.js +19 -15
- package/dist/scripts/extension-distribution-tests.js +98 -211
- package/dist/scripts/extension-tests.js +366 -389
- package/dist/scripts/fact-gate-tests.js +725 -263
- package/dist/scripts/fixtures/extension-bridge-unref-child.mjs +21 -0
- package/dist/scripts/flight-hotel-anchor-363-registered-e2e.js +169 -0
- package/dist/scripts/flight-malformed-tests.js +159 -0
- package/dist/scripts/flyai-tests.js +325 -68
- package/dist/scripts/g5-guard-tests.js +131 -0
- package/dist/scripts/g5-guard.js +189 -0
- package/dist/scripts/gen-lunar-anchors.js +106 -0
- package/dist/scripts/gotry-backend-kernel-tests.js +79 -0
- package/dist/scripts/ground-transfer-tests.js +956 -0
- package/dist/scripts/hbcli-e2e-tests.js +71 -90
- package/dist/scripts/hbcli-live-optin-tests.js +96 -0
- package/dist/scripts/hbcli-release-contract-tests.js +122 -0
- package/dist/scripts/hbcli-tests.js +41 -115
- package/dist/scripts/health-watch-cli.js +42 -28
- package/dist/scripts/hotel-date-gate-tests.js +496 -0
- package/dist/scripts/hotelbyte-reconcile-tests.js +141 -0
- package/dist/scripts/hotelbyte-spawn-e2e-tests.js +373 -0
- package/dist/scripts/i18n-tests.js +16 -9
- package/dist/scripts/incident-tests.js +281 -87
- package/dist/scripts/issue-194-job-id-guard-tests.js +106 -0
- package/dist/scripts/issue-233-cancel-refund-commission-tests.js +392 -0
- package/dist/scripts/issue-271-liveness-tests.js +547 -0
- package/dist/scripts/issue-289-model-retry-real-tests.js +296 -0
- package/dist/scripts/issue-289-model-retry-tests.js +441 -0
- package/dist/scripts/issue-289-web-retry-e2e.js +630 -0
- package/dist/scripts/issue-338-home-city-e2e.js +577 -0
- package/dist/scripts/issue343-real-entry-e2e.js +160 -0
- package/dist/scripts/journey-tests.js +22 -27
- package/dist/scripts/kernel-manifest-evidence.js +109 -0
- package/dist/scripts/kernel-manifest-gate.js +126 -0
- package/dist/scripts/kernel-manifest-tests.js +212 -0
- package/dist/scripts/kernel-manifest-trace-entry.js +7 -0
- package/dist/scripts/kernel-manifest-trace-hook.mjs +28 -0
- package/dist/scripts/kernel-manifest.js +369 -0
- package/dist/scripts/ledger-repair-apply-tests.js +316 -0
- package/dist/scripts/ledger-repair-plan-tests.js +375 -0
- package/dist/scripts/ledger-tests.js +325 -340
- package/dist/scripts/ledger-workflow-crash.js +10 -20
- package/dist/scripts/map-tools-vendor-package-proof.js +206 -134
- package/dist/scripts/memory-capture-tests.js +242 -61
- package/dist/scripts/memory-decay-tests.js +18 -52
- package/dist/scripts/memory-lifecycle-tests.js +657 -0
- package/dist/scripts/memory-lifecycle.js +196 -0
- package/dist/scripts/memory-metrics.js +24 -12
- package/dist/scripts/memory-value-report.js +474 -222
- package/dist/scripts/memory-value-tests.js +328 -0
- package/dist/scripts/metrics-report-tests.js +62 -199
- package/dist/scripts/model-override-e2e.js +66 -105
- package/dist/scripts/nightly-evidence-tests.js +64 -89
- package/dist/scripts/nightly-evidence.js +108 -111
- package/dist/scripts/nudge-digest.js +39 -28
- package/dist/scripts/onboarding-tests.js +63 -88
- package/dist/scripts/opensky-check.js +18 -13
- package/dist/scripts/opensky-tests.js +28 -28
- package/dist/scripts/persona-surface-guard-tests.js +37 -12
- package/dist/scripts/pnpm-dsh-closure-proof.js +2 -5
- package/dist/scripts/policy-anchor-359-registered-e2e.js +214 -0
- package/dist/scripts/price-drift-tests.js +126 -227
- package/dist/scripts/price-drift-watch.js +209 -253
- package/dist/scripts/probe-poi-tests.js +52 -45
- package/dist/scripts/product-metrics.js +187 -273
- package/dist/scripts/publish-preverify.js +47 -41
- package/dist/scripts/realtime-pricing-tests.js +37 -76
- package/dist/scripts/replay-async.js +20 -18
- package/dist/scripts/replay-real.js +16 -18
- package/dist/scripts/replay.js +52 -82
- package/dist/scripts/session-attach-diagnose.js +16 -12
- package/dist/scripts/session-attach-poc.js +34 -37
- package/dist/scripts/session-benchmark.js +66 -147
- package/dist/scripts/session-dida-live-e2e.js +151 -0
- package/dist/scripts/session-extract-tests.js +14 -35
- package/dist/scripts/session-login.js +14 -13
- package/dist/scripts/session-tests.js +545 -583
- package/dist/scripts/sf-live-benchmark.js +92 -110
- package/dist/scripts/sf-live-cli-tests.js +2 -9
- package/dist/scripts/sf-soft-score-tests.js +19 -60
- package/dist/scripts/sf-summary-tests.js +149 -0
- package/dist/scripts/sf-summary.js +466 -84
- package/dist/scripts/skeleton-check.js +16 -14
- package/dist/scripts/skeleton-integration-test.js +11 -10
- package/dist/scripts/skills-contract-tests.js +51 -46
- package/dist/scripts/smoke-session-gate-tests.js +12 -20
- package/dist/scripts/smoke.js +541 -422
- package/dist/scripts/sponsor-reuse-tests.js +262 -0
- package/dist/scripts/state-cli-tests.js +226 -101
- package/dist/scripts/state-cli.js +549 -212
- package/dist/scripts/static-golden-tests.js +46 -180
- package/dist/scripts/time-eval-tests.js +210 -192
- package/dist/scripts/travel-timeline-tests.js +29 -93
- package/dist/scripts/turn-handoff-collect-tests.js +46 -93
- package/dist/scripts/turn-handoff-collect.js +71 -99
- package/dist/scripts/turn-policy-tests.js +28 -29
- package/dist/scripts/typed-contract-canary.js +77 -162
- package/dist/scripts/tz-resolver-sanity.js +50 -0
- package/dist/scripts/tz-resolver-tests.js +584 -0
- package/dist/scripts/unified-tests.js +23 -19
- package/dist/scripts/visa-policy-tests.js +31 -44
- package/dist/scripts/weather-tests.js +121 -543
- package/dist/scripts/wish-channel-gate-tests.js +29 -86
- package/dist/scripts/write-gate-tests.js +522 -0
- package/dist/scripts/z3-lifecycle-fault-tests.js +188 -0
- package/dist/scripts/z3-lifecycle-tests.js +170 -0
- package/dist/scripts/z3-race-repeat-tests.js +39 -0
- package/dist/scripts/z3-race-tests.js +18 -12
- package/dist/src/artifact-gate.js +652 -221
- package/dist/src/backend/kernel.js +91 -0
- package/dist/src/backend/modules/booking-copilot.js +55 -0
- package/dist/src/backend/modules/booking-executor.js +124 -0
- package/dist/src/backend/modules/session-search.js +194 -0
- package/dist/src/benchmark-agent-conformance.js +296 -262
- package/dist/src/benchmark-environment-bridge.js +298 -413
- package/dist/src/benchmark-headless-child-diagnostics.js +93 -100
- package/dist/src/benchmark-tool-isolation.js +94 -67
- package/dist/src/bookable-facts.js +299 -174
- package/dist/src/booking-saga.js +64 -120
- package/dist/src/booking-surface/availability-policy.js +443 -576
- package/dist/src/booking-surface/cancel-refund-commission.js +379 -0
- package/dist/src/booking-surface/contracts.js +24 -80
- package/dist/src/booking-surface/dsh-planner.js +510 -281
- package/dist/src/booking-surface/dsh-plugin.js +17 -1
- package/dist/src/booking-surface/error-codes.js +82 -10
- package/dist/src/booking-surface/index.js +0 -3
- package/dist/src/booking-surface/profile.js +10 -54
- package/dist/src/booking-surface/recovery-chain.js +367 -0
- package/dist/src/booking-surface/runtime.js +765 -891
- package/dist/src/booking-surface/server.js +200 -251
- package/dist/src/booking-surface/startup.js +58 -54
- package/dist/src/booking-surface/validation.js +150 -218
- package/dist/src/bridge.js +20 -13
- package/dist/src/companions.js +48 -74
- package/dist/src/contracts.js +21 -43
- package/dist/src/dsh-llm.js +82 -120
- package/dist/src/engine.js +253 -239
- package/dist/src/evaluation-cadence.js +72 -209
- package/dist/src/evaluation-contracts.js +220 -843
- package/dist/src/flight-pack-adapter.js +54 -0
- package/dist/src/flight-pack-contract.js +2 -0
- package/dist/src/gotry-backend.js +70 -0
- package/dist/src/hotel-date-gate.js +118 -0
- package/dist/src/i18n.js +18 -7
- package/dist/src/index.js +1425 -1629
- package/dist/src/journey.js +132 -81
- package/dist/src/ledger-repair-apply.js +538 -0
- package/dist/src/ledger-repair-plan.js +463 -0
- package/dist/src/loop.js +257 -166
- package/dist/src/memory-capture.js +180 -32
- package/dist/src/memory-decay.js +30 -14
- package/dist/src/memory-lifecycle.js +1310 -0
- package/dist/src/memory-utility.js +27 -40
- package/dist/src/mock-llm.js +36 -61
- package/dist/src/model.js +81 -36
- package/dist/src/realtime-pricing.js +63 -72
- package/dist/src/slot-spec.js +84 -106
- package/dist/src/state-ledger.js +310 -471
- package/dist/src/subagent-job-id-guard.js +58 -0
- package/dist/src/time-anchor.js +231 -33
- package/dist/src/tool-packet.js +20 -8
- package/dist/src/travel-slots.js +58 -35
- package/dist/src/travel-timeline.js +44 -63
- package/dist/src/turn-deadline.js +121 -127
- package/dist/src/turn-policy.js +61 -89
- package/dist/src/tz-resolver.js +143 -0
- package/dist/src/unified.js +504 -381
- package/dist/src/wish-pool.js +39 -14
- package/dist/src/write-gate.js +495 -0
- package/dist/src/z3-shared.js +273 -7
- package/extension/README.md +4 -3
- package/extension/background.js +125 -14
- package/extension/content-bridge.js +23 -1
- package/extension/content-main.js +15 -4
- package/extension/manifest.json +16 -8
- package/package.json +251 -220
- package/ts/capabilities/agent-reach.ts +4 -4
- package/ts/capabilities/anything.ts +1 -1
- package/ts/capabilities/artifacts.ts +46 -9
- package/ts/capabilities/flyai.ts +156 -37
- package/ts/capabilities/hbcli.ts +1 -1
- package/ts/capabilities/incident-log.ts +88 -59
- package/ts/capabilities/session/adapters/ctrip-flight.ts +99 -36
- package/ts/capabilities/session/adapters/dida-portal.ts +250 -0
- package/ts/capabilities/session/adapters/rail-12306.ts +123 -24
- package/ts/capabilities/session/extension-bridge.ts +226 -101
- package/ts/capabilities/session/extension-channel.ts +22 -9
- package/ts/capabilities/session/wizard.ts +2 -2
- package/ts/capabilities/session-consent.ts +98 -14
- package/ts/capabilities/session-login.ts +1 -0
- package/ts/capabilities/session-search.ts +315 -31
- package/ts/dsh-runtime/vendor/README.md +8 -4
- package/ts/dsh-runtime/vendor/dsh-map-tools/README.en.md +7 -1
- package/ts/dsh-runtime/vendor/dsh-map-tools/README.md +5 -3
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/settings-ns.js +1 -1
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/settings-ns.d.ts +1 -1
- package/ts/dsh-runtime/vendor/dsh-map-tools/package.json +6 -6
- package/ts/package.json +236 -16
- package/ts/scripts/map-tools-vendor-package-proof.ts +152 -31
- package/ts/scripts/state-cli.ts +418 -51
- package/ts/src/artifact-gate.ts +561 -15
- package/ts/src/benchmark-environment-bridge.ts +37 -20
- package/ts/src/bookable-facts.ts +183 -7
- package/ts/src/booking-surface/cancel-refund-commission.ts +488 -0
- package/ts/src/booking-surface/dsh-planner.ts +240 -32
- package/ts/src/booking-surface/dsh-plugin.js +17 -1
- package/ts/src/booking-surface/error-codes.ts +75 -0
- package/ts/src/booking-surface/recovery-chain.ts +409 -0
- package/ts/src/booking-surface/server.ts +84 -51
- package/ts/src/booking-surface/validation.ts +2 -0
- package/ts/src/contracts.ts +12 -2
- package/ts/src/dsh-llm.ts +4 -8
- package/ts/src/index.ts +609 -90
- package/ts/src/loop.ts +116 -7
- package/ts/src/memory-capture.ts +227 -3
- package/ts/src/mock-llm.ts +4 -8
- package/ts/src/model.ts +88 -2
- package/ts/src/state-ledger.ts +47 -29
- package/ts/src/subagent-job-id-guard.ts +72 -0
- package/ts/src/time-anchor.ts +217 -13
- package/ts/src/unified.ts +316 -54
package/dist/src/companions.js
CHANGED
|
@@ -1,56 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 同行人档案(memory-design M5 层,P2):同行人及其约束(行动/健康/偏好)的持久化。
|
|
3
|
+
*
|
|
4
|
+
* 立场(memory-design §1):
|
|
5
|
+
* - 溯源 P0:每条约束伴 evidence(用户原话),追加不删史;
|
|
6
|
+
* - 约束只进排序与行程结构建议,永不进硬过滤;
|
|
7
|
+
* - **负面清单守卫**:证件号/电话/地址等敏感字段拒收入库(需要时后端从登录态
|
|
8
|
+
* 填充,fail-closed)——health 存的是「高血压/晕车」这类行为约束,不是病历;
|
|
9
|
+
* - upsert 合并语义同 mergeProfile:追加不删史/同内容幂等。
|
|
10
|
+
*/
|
|
11
|
+
/** 负面清单:命中即拒收(红线 6 + 隐私立场) */
|
|
1
12
|
const SENSITIVE_PATTERNS = [
|
|
2
|
-
{
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
},
|
|
6
|
-
{
|
|
7
|
-
re: /1[3-9]\d{9}/,
|
|
8
|
-
label: '疑似手机号'
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
re: /(护照|身份证|证件号|通行证)\s*号?\s*[::]?\s*\w+/i,
|
|
12
|
-
label: '证件信息'
|
|
13
|
-
}
|
|
13
|
+
{ re: /\d{15,17}[Xx]?/, label: '疑似证件号/卡号' },
|
|
14
|
+
{ re: /1[3-9]\d{9}/, label: '疑似手机号' },
|
|
15
|
+
{ re: /(护照|身份证|证件号|通行证)\s*号?\s*[::]?\s*\w+/i, label: '证件信息' },
|
|
14
16
|
];
|
|
17
|
+
/** 守门:内容命中负面清单 → 返回拒收理由;否则 null */
|
|
15
18
|
export function sensitiveViolation(text) {
|
|
16
|
-
for (const { re, label } of SENSITIVE_PATTERNS){
|
|
17
|
-
if (re.test(text))
|
|
19
|
+
for (const { re, label } of SENSITIVE_PATTERNS) {
|
|
20
|
+
if (re.test(text))
|
|
21
|
+
return `负面清单拒收:${label}不入库(需要时由后端从登录态填充)`;
|
|
18
22
|
}
|
|
19
23
|
return null;
|
|
20
24
|
}
|
|
25
|
+
/** 稳定主键:label 去空白 */
|
|
21
26
|
export function companionId(label) {
|
|
22
27
|
return label.replace(/\s+/g, '');
|
|
23
28
|
}
|
|
24
29
|
function mergeStrArray(oldArr, newArr) {
|
|
25
30
|
const a = oldArr ?? [];
|
|
26
31
|
let added = false;
|
|
27
|
-
for (const x of newArr ?? []){
|
|
32
|
+
for (const x of newArr ?? []) {
|
|
28
33
|
if (!a.includes(x)) {
|
|
29
34
|
a.push(x);
|
|
30
35
|
added = true;
|
|
31
36
|
}
|
|
32
37
|
}
|
|
33
|
-
return {
|
|
34
|
-
merged: a,
|
|
35
|
-
added
|
|
36
|
-
};
|
|
38
|
+
return { merged: a, added };
|
|
37
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* upsert 合并(纯函数,不改入参):同 companion_id 按 label 归并——
|
|
42
|
+
* constraints 逐字段取新值(新值覆盖旧行为约束,追加数组项),evidence 追加不删史,
|
|
43
|
+
* 全量无新增 → 幂等 no-op(appended:false)。
|
|
44
|
+
*/
|
|
38
45
|
export function upsertCompanion(profiles, patch) {
|
|
39
|
-
if (!patch.label?.trim())
|
|
40
|
-
profiles,
|
|
41
|
-
appended: false,
|
|
42
|
-
companionId: '',
|
|
43
|
-
reason: 'label 必填'
|
|
44
|
-
};
|
|
46
|
+
if (!patch.label?.trim())
|
|
47
|
+
return { profiles, appended: false, companionId: '', reason: 'label 必填' };
|
|
45
48
|
const violation = sensitiveViolation(JSON.stringify(patch));
|
|
46
|
-
if (violation)
|
|
47
|
-
profiles,
|
|
48
|
-
appended: false,
|
|
49
|
-
companionId: '',
|
|
50
|
-
reason: violation
|
|
51
|
-
};
|
|
49
|
+
if (violation)
|
|
50
|
+
return { profiles, appended: false, companionId: '', reason: violation };
|
|
52
51
|
const id = companionId(patch.label);
|
|
53
|
-
const existing = profiles.find(
|
|
52
|
+
const existing = profiles.find(p => p.companion_id === id);
|
|
54
53
|
if (!existing) {
|
|
55
54
|
const full = {
|
|
56
55
|
schema: 'companion_profile.v1',
|
|
@@ -58,55 +57,30 @@ export function upsertCompanion(profiles, patch) {
|
|
|
58
57
|
label: patch.label.trim(),
|
|
59
58
|
constraints: {
|
|
60
59
|
mobility: patch.constraints.mobility,
|
|
61
|
-
health: patch.constraints.health ? [
|
|
62
|
-
|
|
63
|
-
] : undefined,
|
|
64
|
-
prefs: patch.constraints.prefs ? [
|
|
65
|
-
...patch.constraints.prefs
|
|
66
|
-
] : undefined
|
|
60
|
+
health: patch.constraints.health ? [...patch.constraints.health] : undefined,
|
|
61
|
+
prefs: patch.constraints.prefs ? [...patch.constraints.prefs] : undefined,
|
|
67
62
|
},
|
|
68
|
-
evidence: [
|
|
69
|
-
|
|
70
|
-
],
|
|
71
|
-
ts: new Date().toISOString()
|
|
72
|
-
};
|
|
73
|
-
return {
|
|
74
|
-
profiles: [
|
|
75
|
-
...profiles,
|
|
76
|
-
full
|
|
77
|
-
],
|
|
78
|
-
appended: true,
|
|
79
|
-
companionId: id
|
|
63
|
+
evidence: [patch.evidence],
|
|
64
|
+
ts: new Date().toISOString(),
|
|
80
65
|
};
|
|
66
|
+
return { profiles: [...profiles, full], appended: true, companionId: id };
|
|
81
67
|
}
|
|
82
68
|
const mergedConstraints = {
|
|
83
69
|
mobility: patch.constraints.mobility ?? existing.constraints.mobility,
|
|
84
70
|
health: mergeStrArray(existing.constraints.health, patch.constraints.health).merged,
|
|
85
|
-
prefs: mergeStrArray(existing.constraints.prefs, patch.constraints.prefs).merged
|
|
71
|
+
prefs: mergeStrArray(existing.constraints.prefs, patch.constraints.prefs).merged,
|
|
86
72
|
};
|
|
87
|
-
const ev = mergeStrArray(existing.evidence, [
|
|
88
|
-
patch.evidence
|
|
89
|
-
]);
|
|
73
|
+
const ev = mergeStrArray(existing.evidence, [patch.evidence]);
|
|
90
74
|
const healthLen = mergedConstraints.health?.length ?? 0;
|
|
91
75
|
const prefsLen = mergedConstraints.prefs?.length ?? 0;
|
|
92
|
-
const changed = mergedConstraints.mobility !== existing.constraints.mobility ||
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const next = profiles.map(
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
ts: new Date().toISOString()
|
|
103
|
-
} : p);
|
|
104
|
-
return {
|
|
105
|
-
profiles: next,
|
|
106
|
-
appended: true,
|
|
107
|
-
companionId: id
|
|
108
|
-
};
|
|
76
|
+
const changed = mergedConstraints.mobility !== existing.constraints.mobility ||
|
|
77
|
+
healthLen !== (existing.constraints.health?.length ?? 0) ||
|
|
78
|
+
prefsLen !== (existing.constraints.prefs?.length ?? 0) ||
|
|
79
|
+
ev.added;
|
|
80
|
+
if (!changed)
|
|
81
|
+
return { profiles, appended: false, companionId: id };
|
|
82
|
+
const next = profiles.map(p => p.companion_id === id
|
|
83
|
+
? { ...p, constraints: mergedConstraints, evidence: ev.merged, ts: new Date().toISOString() }
|
|
84
|
+
: p);
|
|
85
|
+
return { profiles: next, appended: true, companionId: id };
|
|
109
86
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
//# sourceURL=ts/src/companions.ts
|
package/dist/src/contracts.js
CHANGED
|
@@ -1,64 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage 1 契约层(S1,docs/design/stage1-top-down-design.md §2)——顶层数据与工具面契约。
|
|
3
|
+
*
|
|
4
|
+
* 自顶向下纪律:本文件是唯一权威契约。实现(mock 循环/求解器挂载/真 LLM)都向这里对齐;
|
|
5
|
+
* 契约变更需走设计文档升版,不随实现漂移。
|
|
6
|
+
* 责任铁律:LLM 只做问句组织/翻译/解释;判定与算术永远是确定性组件。
|
|
7
|
+
*/
|
|
8
|
+
/** 工具注册表:名字 → IO 类型(dsh 插件按此生成 parameters/output schema) */
|
|
1
9
|
export const TOOL_CONTRACTS = {
|
|
2
10
|
'gotry_interview_next': {},
|
|
3
11
|
'gotry_spec_extract': {},
|
|
4
12
|
'gotry_solve': {},
|
|
5
13
|
'gotry_render': {},
|
|
6
|
-
'gotry_wish_pool_add': {}
|
|
14
|
+
'gotry_wish_pool_add': {},
|
|
7
15
|
};
|
|
16
|
+
// ---- wire schema(dsh 注册用的 JSON Schema 面;type:'json' 根 + 关键字段文档) ----
|
|
8
17
|
export const TRIP_STATE_JSON_SCHEMA = {
|
|
9
18
|
type: 'object',
|
|
10
19
|
additionalProperties: false,
|
|
11
20
|
properties: {
|
|
12
21
|
calendar: {
|
|
13
|
-
type: 'object',
|
|
14
|
-
|
|
15
|
-
description: '年份与已断言的星期映射;一次断言终身使用,冲突必须显式指出'
|
|
22
|
+
type: 'object', additionalProperties: true,
|
|
23
|
+
description: '年份与已断言的星期映射;一次断言终身使用,冲突必须显式指出',
|
|
16
24
|
},
|
|
17
25
|
profile: {
|
|
18
|
-
type: 'object',
|
|
19
|
-
|
|
20
|
-
description: 'workWindow(带 evidence)/companions/budgetTier/bookedResources/motivation'
|
|
21
|
-
},
|
|
22
|
-
spec: {
|
|
23
|
-
type: 'json',
|
|
24
|
-
description: '统一行程模型 JourneySpec(见 unified.ts)'
|
|
25
|
-
},
|
|
26
|
-
solve: {
|
|
27
|
-
type: 'json',
|
|
28
|
-
description: '求解结果(锚点/排除/红旗/建议)'
|
|
26
|
+
type: 'object', additionalProperties: true,
|
|
27
|
+
description: 'workWindow(带 evidence)/companions/budgetTier/bookedResources/motivation',
|
|
29
28
|
},
|
|
29
|
+
spec: { type: 'json', description: '统一行程模型 JourneySpec(见 unified.ts)' },
|
|
30
|
+
solve: { type: 'json', description: '求解结果(锚点/排除/红旗/建议)' },
|
|
30
31
|
gates: {
|
|
31
32
|
type: 'array',
|
|
32
33
|
description: '待决问题,只能是选择题',
|
|
33
34
|
items: {
|
|
34
|
-
type: 'object',
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
id: {
|
|
38
|
-
type: 'string'
|
|
39
|
-
},
|
|
40
|
-
question: {
|
|
41
|
-
type: 'string'
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
35
|
+
type: 'object', additionalProperties: true,
|
|
36
|
+
properties: { id: { type: 'string' }, question: { type: 'string' } },
|
|
37
|
+
},
|
|
45
38
|
},
|
|
46
|
-
wishes: {
|
|
47
|
-
type: 'array',
|
|
48
|
-
description: '「下一次出发」清单',
|
|
49
|
-
items: {
|
|
50
|
-
type: 'object',
|
|
51
|
-
additionalProperties: true
|
|
52
|
-
}
|
|
53
|
-
}
|
|
39
|
+
wishes: { type: 'array', description: '「下一次出发」清单', items: { type: 'object', additionalProperties: true } },
|
|
54
40
|
},
|
|
55
|
-
required: [
|
|
56
|
-
'calendar',
|
|
57
|
-
'profile',
|
|
58
|
-
'gates',
|
|
59
|
-
'wishes'
|
|
60
|
-
]
|
|
41
|
+
required: ['calendar', 'profile', 'gates', 'wishes'],
|
|
61
42
|
};
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
//# sourceURL=ts/src/contracts.ts
|
package/dist/src/dsh-llm.js
CHANGED
|
@@ -1,39 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 真 LlmPort:OpenAI 兼容接口的 provider 中立适配器(DeepSeek/MiniMax-M2 实测)。
|
|
3
|
+
* 零新依赖(node 内建 fetch)。环境变量:LLM_API_KEY/LLM_BASE_URL/LLM_MODEL
|
|
4
|
+
* (兼容旧 DEEPSEEK_* 别名)。MiniMax-M2 是推理模型:输出带 <think> 块,
|
|
5
|
+
* 必须先剥离再解析——JSON 藏在 think 里是常见失败模式。
|
|
6
|
+
* 无 key 时抛出明确错误,replay-real 自动回退 mock(ADR-8)。
|
|
7
|
+
* 责任铁律不变:本适配器只做翻译/润色/解释,判定与算术在确定性组件。
|
|
8
|
+
*/
|
|
1
9
|
import { parseFlightPackToSpec } from './unified.js';
|
|
2
10
|
import { buildTimeAnchor } from './time-anchor.js';
|
|
3
11
|
import { buildSlotSystem, flagExpiredSlots, normalizeExtraction } from './travel-slots.js';
|
|
4
|
-
|
|
5
|
-
|
|
12
|
+
import { mergeProfileWorkWindow } from './flight-pack-adapter.js';
|
|
13
|
+
// 惰性读取(env 在调用时取值):模块顶常量会在 .env 加载前冻结(ESM import 提升),
|
|
14
|
+
// 脚本先 loadEnv 再 import 也救不了——401 错配(key 发往默认端点)的存量隐患由此根除。
|
|
15
|
+
const model = () => process.env['LLM_MODEL'] ?? process.env['DEEPSEEK_MODEL'] ?? 'MiniMax-M2';
|
|
16
|
+
const base = () => (process.env['LLM_BASE_URL'] ?? process.env['DEEPSEEK_BASE_URL'] ?? 'https://api.minimax.io/v1').replace(/\/$/, '');
|
|
6
17
|
function emptyUsage() {
|
|
7
|
-
return {
|
|
8
|
-
calls: 0,
|
|
9
|
-
inputTokens: 0,
|
|
10
|
-
outputTokens: 0,
|
|
11
|
-
inputCacheHitTokens: 0,
|
|
12
|
-
inputCacheMissTokens: 0,
|
|
13
|
-
responsesMissingUsage: 0
|
|
14
|
-
};
|
|
18
|
+
return { calls: 0, inputTokens: 0, outputTokens: 0, inputCacheHitTokens: 0, inputCacheMissTokens: 0, responsesMissingUsage: 0 };
|
|
15
19
|
}
|
|
16
20
|
async function chat(messages, json, usage) {
|
|
17
21
|
const key = process.env['LLM_API_KEY'] ?? process.env['DEEPSEEK_API_KEY'];
|
|
18
|
-
if (!key)
|
|
22
|
+
if (!key)
|
|
23
|
+
throw new Error('LLM_API_KEY 未设置(兼容 DEEPSEEK_API_KEY 别名)——真 LLM 路径不可用,请回退 mock(ADR-8)');
|
|
19
24
|
const res = await fetch(`${base()}/chat/completions`, {
|
|
20
25
|
method: 'POST',
|
|
21
|
-
headers: {
|
|
22
|
-
'Content-Type': 'application/json',
|
|
23
|
-
Authorization: `Bearer ${key}`
|
|
24
|
-
},
|
|
26
|
+
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${key}` },
|
|
25
27
|
body: JSON.stringify({
|
|
26
28
|
model: model(),
|
|
27
29
|
messages,
|
|
28
|
-
...json ? {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
} : {},
|
|
33
|
-
temperature: json ? 0 : 0.7
|
|
34
|
-
})
|
|
30
|
+
...(json ? { response_format: { type: 'json_object' } } : {}),
|
|
31
|
+
temperature: json ? 0 : 0.7,
|
|
32
|
+
}),
|
|
35
33
|
});
|
|
36
|
-
if (!res.ok)
|
|
34
|
+
if (!res.ok)
|
|
35
|
+
throw new Error(`llm ${res.status}: ${(await res.text()).slice(0, 300)}`);
|
|
37
36
|
const data = await res.json();
|
|
38
37
|
if (usage) {
|
|
39
38
|
usage.calls += 1;
|
|
@@ -42,157 +41,120 @@ async function chat(messages, json, usage) {
|
|
|
42
41
|
usage.inputTokens += u.prompt_tokens ?? 0;
|
|
43
42
|
usage.outputTokens += u.completion_tokens ?? 0;
|
|
44
43
|
usage.inputCacheHitTokens += u.prompt_cache_hit_tokens ?? 0;
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
// 无缓存明细的 provider:全部输入按 miss 记(随后按 peak miss 价换算,只高不低)
|
|
45
|
+
usage.inputCacheMissTokens += u.prompt_cache_miss_tokens ?? (u.prompt_tokens ?? 0);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
47
48
|
usage.responsesMissingUsage += 1;
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
const raw = data.choices[0]?.message?.content ?? '';
|
|
52
|
+
// 推理模型(MiniMax-M2 等):剥 <think> 块,只留正文;未闭合时留全文由上层容错
|
|
51
53
|
return raw.replace(/<think>[\s\S]*?<\/think>/g, '').trim() || raw;
|
|
52
54
|
}
|
|
55
|
+
/** 从模型输出稳健地抠出 JSON 对象(容忍围栏/前后文) */
|
|
53
56
|
function parseJsonBlock(text) {
|
|
54
57
|
const m = text.match(/\{[\s\S]*\}/);
|
|
55
|
-
if (!m)
|
|
58
|
+
if (!m)
|
|
59
|
+
return null;
|
|
56
60
|
try {
|
|
57
61
|
return JSON.parse(m[0]);
|
|
58
|
-
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
59
64
|
return null;
|
|
60
65
|
}
|
|
61
66
|
}
|
|
62
67
|
const FACTS_SYSTEM = `你是旅行规划的事实抽取器。从对话中抽取两类事实并以 JSON 返回:
|
|
63
68
|
{"calendar": {"year": 数字, "assertedWeekdays": {"YYYY-MM-DD": "mon|tue|wed|thu|fri|sat|sun"}},
|
|
64
|
-
"profile": {"workWindow": {"homeTzOffsetMin":
|
|
69
|
+
"profile": {"workWindow": {"homeTzOffsetMin": 数字(仅 legacy v1;用户未明确时可省略), "startMin": 数字, "endMin": 数字, "workdays": [0,1,2,3,4], "evidence": "用户原话"},
|
|
65
70
|
"companions": ["..."], "budgetTier": "economy|comfort|convenience",
|
|
66
71
|
"bookedResources": [{"kind": "flight|hotel", "ref": "...", "window": "..."}]}}
|
|
67
|
-
只放用户明确说过的事实;没有的字段省略。分钟数从 HH:MM
|
|
72
|
+
只放用户明确说过的事实;没有的字段省略。分钟数从 HH:MM 换算;用户未明确说 numeric offset 时不要猜、不要输出 homeTzOffsetMin;v2 pack 的 IANA home zone 属于数据层权威。
|
|
68
73
|
**休假语义(关键)**:用户说「请假/年假/不用办公/休假」→ workWindow 输出 {"vacation": true}(不是省略!省略会触发重复追问);只有用户明确给了工作时间才输出完整 workWindow 对象。只输出 JSON。`;
|
|
69
74
|
const SKELETON_SYSTEM = `你是行程骨架抽取器。从对话中抽取行程的**骨架**——段(移动)与锚点,不包含任何班次数据(班次来自数据层,你不要编造时刻/价格/航班号)。
|
|
70
75
|
输出 JSON:{"scenario":"erhai|workation|yunnan|generic","segments":[{"id":"f1","role":"choice|fixed","route":"HKG->HKT","dateHint":"2026-07-18","anchors":{"arriveByMin":885}}]}
|
|
71
76
|
规则:每个跨城移动一段;锚点只放用户明说或必然的(如"当天到"→arriveByMin 23:59=1439);时刻用当日分钟。
|
|
72
77
|
scenario 判定:「洱海/大理/千岛湖/太湖+选目的地」→erhai(候选集);「普吉/workation/远程办公+多城链」→workation(五段链);「云南/大理丽江」→yunnan;不确定→generic。只输出 JSON。`;
|
|
73
|
-
export function createOpenAICompatLlm(flightPackPath, clock = ()=>new Date()) {
|
|
78
|
+
export function createOpenAICompatLlm(flightPackPath, clock = () => new Date()) {
|
|
74
79
|
const pack = flightPackPath;
|
|
75
80
|
const usage = emptyUsage();
|
|
76
|
-
const historyText = (h)=>h.map(
|
|
77
|
-
|
|
81
|
+
const historyText = (h) => h.map(t => `${t.role === 'user' ? '用户' : '助手'}: ${t.text}`).join('\n');
|
|
82
|
+
// 时间锚点卡:每条抽取链路都带上「今天」——legacy 路径此前无时间注入,
|
|
83
|
+
// 过期/相对日期语义全靠它(算术在 time-anchor 层,LLM 只查卡)。
|
|
84
|
+
const anchorContext = () => `时间锚点卡:\n${buildTimeAnchor(clock()).card}`;
|
|
78
85
|
return {
|
|
79
|
-
async extractFacts
|
|
80
|
-
const out = await chat([
|
|
81
|
-
{
|
|
82
|
-
role: 'system',
|
|
83
|
-
content: FACTS_SYSTEM
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
role: 'user',
|
|
87
|
-
content: `${anchorContext()}\n\n${historyText(history)}`
|
|
88
|
-
}
|
|
89
|
-
], true, usage);
|
|
86
|
+
async extractFacts(history) {
|
|
87
|
+
const out = await chat([{ role: 'system', content: FACTS_SYSTEM }, { role: 'user', content: `${anchorContext()}\n\n${historyText(history)}` }], true, usage);
|
|
90
88
|
const obj = parseJsonBlock(out);
|
|
91
|
-
if (!obj)
|
|
92
|
-
assumptions: []
|
|
93
|
-
};
|
|
89
|
+
if (!obj)
|
|
90
|
+
return { assumptions: [] };
|
|
94
91
|
const calendar = obj['calendar'];
|
|
95
92
|
const profile = obj['profile'];
|
|
96
|
-
const assumptions = Object.keys(profile ?? {}).map(
|
|
97
|
-
|
|
98
|
-
source: 'user-verbatim'
|
|
99
|
-
}));
|
|
100
|
-
return {
|
|
101
|
-
calendar,
|
|
102
|
-
profile,
|
|
103
|
-
assumptions
|
|
104
|
-
};
|
|
93
|
+
const assumptions = Object.keys(profile ?? {}).map(f => ({ field: f, source: 'user-verbatim' }));
|
|
94
|
+
return { calendar, profile, assumptions };
|
|
105
95
|
},
|
|
106
|
-
async extractSpec
|
|
96
|
+
async extractSpec(history, state) {
|
|
97
|
+
// 架构(ADR-10):LLM 只产骨架与锚点;班次数据永远来自能力层(数据包/未来实时API)
|
|
107
98
|
const context = `${anchorContext()}\n已断言日历:${JSON.stringify(state.calendar.assertedWeekdays)}\nprofile:${JSON.stringify(state.profile)}`;
|
|
108
|
-
const out = await chat([
|
|
109
|
-
{
|
|
110
|
-
role: 'system',
|
|
111
|
-
content: SKELETON_SYSTEM
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
role: 'user',
|
|
115
|
-
content: `${context}\n\n${historyText(history)}`
|
|
116
|
-
}
|
|
117
|
-
], true, usage);
|
|
99
|
+
const out = await chat([{ role: 'system', content: SKELETON_SYSTEM }, { role: 'user', content: `${context}\n\n${historyText(history)}` }], true, usage);
|
|
118
100
|
const skeleton = parseJsonBlock(out);
|
|
119
|
-
if (!skeleton || !Array.isArray(skeleton['segments']) || skeleton['segments'].length === 0)
|
|
120
|
-
|
|
101
|
+
if (!skeleton || !Array.isArray(skeleton['segments']) || skeleton['segments'].length === 0)
|
|
102
|
+
return null;
|
|
103
|
+
// 能力层装数据:航班包提供 services;骨架按段 id 合并锚点
|
|
104
|
+
if (!pack)
|
|
105
|
+
return null;
|
|
121
106
|
const { readFile } = await import('node:fs/promises');
|
|
122
107
|
const scenario = String(skeleton['scenario'] ?? 'generic');
|
|
123
|
-
|
|
108
|
+
// 场景→数据包路由(薄壳段3:意图决定装哪个包,而非永远装通用包)
|
|
109
|
+
// generic 不装包——意图不明确时不进求解,让循环继续访谈(ADR-10:翻译不造数)
|
|
110
|
+
if (scenario === 'generic')
|
|
111
|
+
return null;
|
|
124
112
|
const packByScenario = {
|
|
125
113
|
erhai: pack.replace('flights_2026.json', 'golden_erhai.json'),
|
|
126
|
-
workation: pack,
|
|
127
|
-
yunnan: pack.replace('flights_2026.json', 'yunnan-pack.json')
|
|
114
|
+
workation: pack, // 五段链
|
|
115
|
+
yunnan: pack.replace('flights_2026.json', 'yunnan-pack.json'),
|
|
128
116
|
};
|
|
129
117
|
const packPath = packByScenario[scenario];
|
|
130
|
-
if (!packPath)
|
|
118
|
+
if (!packPath)
|
|
119
|
+
return null;
|
|
131
120
|
let packSpec;
|
|
132
121
|
try {
|
|
133
122
|
if (scenario === 'erhai') {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
budgetCny: 3000
|
|
138
|
-
};
|
|
123
|
+
// 洱海 = 候选集场景:不装五段链,返回洱海候选 spec 的轻量标记(由引擎的候选求解处理;
|
|
124
|
+
// 循环层看到 scenario=erhai 时走 solveChoiceSegment 而非 solveUnified)
|
|
125
|
+
return { segments: [], note: 'erhai-candidates', budgetCny: 3000 };
|
|
139
126
|
}
|
|
140
127
|
packSpec = parseFlightPackToSpec(JSON.parse(await readFile(packPath, 'utf-8')));
|
|
141
|
-
}
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
142
130
|
return null;
|
|
143
131
|
}
|
|
144
|
-
const anchorsById = new Map(skeleton['segments'].map((s)
|
|
145
|
-
|
|
146
|
-
s['anchors'] ?? {}
|
|
147
|
-
]));
|
|
148
|
-
for (const seg of packSpec.segments){
|
|
132
|
+
const anchorsById = new Map(skeleton['segments'].map(s => [String(s['id'] ?? ''), (s['anchors'] ?? {})]));
|
|
133
|
+
for (const seg of packSpec.segments) {
|
|
149
134
|
const a = anchorsById.get(seg.id);
|
|
150
|
-
if (a?.arriveByMin !== undefined)
|
|
151
|
-
arriveByMin: a.arriveByMin
|
|
152
|
-
};
|
|
135
|
+
if (a?.arriveByMin !== undefined)
|
|
136
|
+
seg.anchors = { arriveByMin: a.arriveByMin };
|
|
153
137
|
}
|
|
154
|
-
packSpec
|
|
155
|
-
homeTzOffsetMin: state.profile.workWindow.homeTzOffsetMin,
|
|
156
|
-
startMin: state.profile.workWindow.startMin,
|
|
157
|
-
endMin: state.profile.workWindow.endMin,
|
|
158
|
-
workdays: state.profile.workWindow.workdays
|
|
159
|
-
} : undefined;
|
|
138
|
+
packSpec = mergeProfileWorkWindow(packSpec, state.profile.workWindow);
|
|
160
139
|
packSpec.budgetCny = 9000;
|
|
161
140
|
return packSpec;
|
|
162
141
|
},
|
|
163
|
-
async extractSlots
|
|
142
|
+
async extractSlots(history, now) {
|
|
143
|
+
// now 可注入(评测固定锚点);过期判定在 flagExpiredSlots(代码层),模型只管逐字抽取
|
|
164
144
|
const anchor = buildTimeAnchor(now ?? clock());
|
|
165
|
-
const out = await chat([
|
|
166
|
-
{
|
|
167
|
-
role: 'system',
|
|
168
|
-
content: buildSlotSystem(anchor)
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
role: 'user',
|
|
172
|
-
content: historyText(history)
|
|
173
|
-
}
|
|
174
|
-
], true, usage);
|
|
145
|
+
const out = await chat([{ role: 'system', content: buildSlotSystem(anchor) }, { role: 'user', content: historyText(history) }], true, usage);
|
|
175
146
|
const obj = parseJsonBlock(out);
|
|
176
|
-
if (!obj)
|
|
177
|
-
|
|
147
|
+
if (!obj)
|
|
148
|
+
return null;
|
|
149
|
+
// language 判定归代码层(detectLanguage),模型输出仅供参考;过期判定同在代码层
|
|
150
|
+
const ext = normalizeExtraction(obj, history.map(t => t.text).join('\n'));
|
|
178
151
|
return ext ? flagExpiredSlots(ext, anchor) : null;
|
|
179
152
|
},
|
|
180
|
-
async polishQuestion
|
|
181
|
-
const out = await chat([
|
|
182
|
-
{
|
|
183
|
-
role: 'system',
|
|
184
|
-
content: '把旅行规划的追问润色得更自然,保留全部信息(含为什么问),一两句话,不要加表情。'
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
role: 'user',
|
|
188
|
-
content: `【${q.key}】${q.text}(为什么问:${q.why})`
|
|
189
|
-
}
|
|
190
|
-
], false, usage);
|
|
153
|
+
async polishQuestion(q) {
|
|
154
|
+
const out = await chat([{ role: 'system', content: '把旅行规划的追问润色得更自然,保留全部信息(含为什么问),一两句话,不要加表情。' },
|
|
155
|
+
{ role: 'user', content: `【${q.key}】${q.text}(为什么问:${q.why})` }], false, usage);
|
|
191
156
|
return out.trim() || `【${q.key}】${q.text}`;
|
|
192
157
|
},
|
|
193
|
-
usage
|
|
158
|
+
usage,
|
|
194
159
|
};
|
|
195
160
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
//# sourceURL=ts/src/dsh-llm.ts
|