@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
|
@@ -1,78 +1,59 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* 旅行时间线(memory-design M4 层,P1):「去过哪、何时、和谁」的 append-only 事实层。
|
|
3
|
+
*
|
|
4
|
+
* 立场(memory-design §1):确定性事实归代码——日期解析复用 slot-spec(锚点卡词表+绝对),
|
|
5
|
+
* 词表外 unresolved 不猜;每条事件必须带 evidence(用户原话或 wish 确认),溯源 P0。
|
|
6
|
+
* 消费:出发地三级解析(未来行程→时间线→问用户)/「去过不再推」排序通道/
|
|
7
|
+
* 回流率分子(verified_outcome ⟺ timeline 有对应行程)。
|
|
8
|
+
* 多用户前向兼容:append-only + 稳定 trip_id,账本化只换存储面(RFC §6.5)。
|
|
9
|
+
*/
|
|
10
|
+
import { ymd } from './time-anchor.js';
|
|
2
11
|
import { resolveSlotDate } from './slot-spec.js';
|
|
12
|
+
/** 相对/模糊表达 → 绝对日期(守门:词表外返回 null,调用方必须拒收而非猜) */
|
|
3
13
|
export function resolveTimelineDate(expr, anchor) {
|
|
4
14
|
return resolveSlotDate(expr, anchor).date;
|
|
5
15
|
}
|
|
16
|
+
/** 语义主键:同目的地+同 start+同 source = 同一行程(重放 no-op) */
|
|
6
17
|
export function makeTripId(ev) {
|
|
7
18
|
return `${ev.destination}|${ev.start}|${ev.source}`.replace(/\s+/g, '_');
|
|
8
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* 追加守门(纯函数,不改入参):
|
|
22
|
+
* - destination/evidence 必填,start 必须已是绝对日期(YYYY-MM-DD),否则拒收(null);
|
|
23
|
+
* - end < start 拒收;
|
|
24
|
+
* - 同 trip_id 已存在 → no-op(返回 appended:false,幂等);
|
|
25
|
+
* - 同目的地日期区间重叠(不同 trip_id)→ 拒收(冲突即停,由人裁决)。
|
|
26
|
+
*/
|
|
9
27
|
export function appendTrip(events, ev) {
|
|
10
|
-
if (!ev.destination?.trim())
|
|
11
|
-
events,
|
|
12
|
-
|
|
13
|
-
reason: '
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
appended: false,
|
|
18
|
-
reason: 'evidence 必填(用户原话或 wish 确认指针)'
|
|
19
|
-
};
|
|
20
|
-
if (!/^\d{4}-\d{2}-\d{2}$/.test(ev.start)) return {
|
|
21
|
-
events,
|
|
22
|
-
appended: false,
|
|
23
|
-
reason: 'start 必须为 YYYY-MM-DD(词表外日期由上游解析,不猜)'
|
|
24
|
-
};
|
|
25
|
-
if (ev.end && ev.end < ev.start) return {
|
|
26
|
-
events,
|
|
27
|
-
appended: false,
|
|
28
|
-
reason: 'end 早于 start'
|
|
29
|
-
};
|
|
28
|
+
if (!ev.destination?.trim())
|
|
29
|
+
return { events, appended: false, reason: 'destination 必填' };
|
|
30
|
+
if (!ev.evidence?.trim())
|
|
31
|
+
return { events, appended: false, reason: 'evidence 必填(用户原话或 wish 确认指针)' };
|
|
32
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(ev.start))
|
|
33
|
+
return { events, appended: false, reason: 'start 必须为 YYYY-MM-DD(词表外日期由上游解析,不猜)' };
|
|
34
|
+
if (ev.end && ev.end < ev.start)
|
|
35
|
+
return { events, appended: false, reason: 'end 早于 start' };
|
|
30
36
|
const tripId = makeTripId(ev);
|
|
31
|
-
if (events.some(
|
|
32
|
-
events,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
events,
|
|
39
|
-
appended: false,
|
|
40
|
-
tripId: overlap.trip_id,
|
|
41
|
-
reason: `与已有行程 ${overlap.trip_id} 日期重叠,冲突即停`
|
|
42
|
-
};
|
|
43
|
-
const full = {
|
|
44
|
-
schema: 'travel_timeline.v1',
|
|
45
|
-
trip_id: tripId,
|
|
46
|
-
ts: new Date().toISOString(),
|
|
47
|
-
...ev
|
|
48
|
-
};
|
|
49
|
-
return {
|
|
50
|
-
events: [
|
|
51
|
-
...events,
|
|
52
|
-
full
|
|
53
|
-
],
|
|
54
|
-
appended: true,
|
|
55
|
-
tripId
|
|
56
|
-
};
|
|
37
|
+
if (events.some(e => e.trip_id === tripId))
|
|
38
|
+
return { events, appended: false, tripId };
|
|
39
|
+
const overlap = events.find(e => e.destination === ev.destination && !(e.end && e.end < ev.start) && !(ev.end && ev.end < e.start));
|
|
40
|
+
if (overlap)
|
|
41
|
+
return { events, appended: false, tripId: overlap.trip_id, reason: `与已有行程 ${overlap.trip_id} 日期重叠,冲突即停` };
|
|
42
|
+
const full = { schema: 'travel_timeline.v1', trip_id: tripId, ts: new Date().toISOString(), ...ev };
|
|
43
|
+
return { events: [...events, full], appended: true, tripId };
|
|
57
44
|
}
|
|
45
|
+
/** 只读投影:按 start 倒序的行程摘要(「去过」行/brief 注入用) */
|
|
58
46
|
export function projectTimeline(events) {
|
|
59
|
-
return [
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
tripId: e.trip_id,
|
|
63
|
-
destination: e.destination,
|
|
64
|
-
start: e.start,
|
|
65
|
-
end: e.end,
|
|
66
|
-
companions: e.companions
|
|
67
|
-
}));
|
|
47
|
+
return [...events]
|
|
48
|
+
.sort((a, b) => (a.start < b.start ? 1 : -1))
|
|
49
|
+
.map(e => ({ tripId: e.trip_id, destination: e.destination, start: e.start, end: e.end, companions: e.companions }));
|
|
68
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* 交叉一致(回流率分子的质变):verified_outcome 的 wish 应有对应时间线行程。
|
|
53
|
+
* 返回缺口清单(verified 但无 timeline)——巡检口径,不自动补写(补写需要用户确认日期)。
|
|
54
|
+
*/
|
|
69
55
|
export function timelineGapsForVerified(timeline, verifiedWishes) {
|
|
70
|
-
const dests = new Set(timeline.map(
|
|
71
|
-
return verifiedWishes.filter(
|
|
72
|
-
wishId: w.wishId
|
|
73
|
-
}));
|
|
56
|
+
const dests = new Set(timeline.map(t => t.destination));
|
|
57
|
+
return verifiedWishes.filter(w => w.destination && !dests.has(w.destination)).map(w => ({ wishId: w.wishId }));
|
|
74
58
|
}
|
|
75
59
|
export { ymd };
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
//# sourceURL=ts/src/travel-timeline.ts
|
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-agent, per-turn wall-clock boundary driven by routing (ADR-24 v2).
|
|
3
|
+
*
|
|
4
|
+
* 职责只有一件:保证每一轮终结在三态之一——当面答完(converge)、转后台
|
|
5
|
+
* 并给出回访承诺(handoff)、或明确暂停。绝不允许第四态:流死掉、什么
|
|
6
|
+
* 都没交付(2026-09-02 轨迹的失败形态)。
|
|
7
|
+
*
|
|
8
|
+
* - 阈值不再固定:每次 user/message 由 `turn-policy.ts` 的确定性分类器
|
|
9
|
+
* 解析 TurnPolicy(softMs/hardMs/exit);benchmark opt-in 用 fixedPolicy
|
|
10
|
+
* 钉死以保证可复现。
|
|
11
|
+
* - 硬阈拒绝时**同步**抑制工具 schema(防同 step 回环),并按 exit 语义
|
|
12
|
+
* 返回两种结构化结果:converge=用已有证据作答;handoff=落
|
|
13
|
+
* `gotry_turn_handoff.v1` 工单并指令模型告知用户 ETA 与回访方式。
|
|
14
|
+
* - handoff 工单是**新的独立格式**,落在 `<stateRoot>/gotry-state/
|
|
15
|
+
* turn-handoffs/`,不与 `async/` 的 loop 求解工单混用——async-collect
|
|
16
|
+
* 对无 spec 的 state 会立即结算 failed(假失败),收集器是未来的
|
|
17
|
+
* agent tick(loopx),不是 async-collect。
|
|
18
|
+
*/
|
|
1
19
|
import { randomUUID } from 'node:crypto';
|
|
2
20
|
import { mkdir, readdir, readFile, rename, writeFile } from 'node:fs/promises';
|
|
3
21
|
import { join } from 'node:path';
|
|
@@ -14,7 +32,7 @@ export async function writeTurnHandoffTicket(stateRoot, userMessage) {
|
|
|
14
32
|
userMessage,
|
|
15
33
|
requestedAt: new Date().toISOString(),
|
|
16
34
|
etaLabel: TURN_HANDOFF_ETA_LABEL,
|
|
17
|
-
status: 'open'
|
|
35
|
+
status: 'open',
|
|
18
36
|
};
|
|
19
37
|
await writeTicketJson(stateRoot, ticket);
|
|
20
38
|
return ticket;
|
|
@@ -25,20 +43,20 @@ function handoffDir(stateRoot) {
|
|
|
25
43
|
}
|
|
26
44
|
async function writeTicketJson(stateRoot, ticket) {
|
|
27
45
|
const dir = handoffDir(stateRoot);
|
|
28
|
-
await mkdir(dir, {
|
|
29
|
-
recursive: true
|
|
30
|
-
});
|
|
46
|
+
await mkdir(dir, { recursive: true });
|
|
31
47
|
const path = join(dir, `${ticket.id}.json`);
|
|
32
48
|
const tmp = `${path}.tmp`;
|
|
33
49
|
await writeFile(tmp, JSON.stringify(ticket, null, 2), 'utf-8');
|
|
34
50
|
await rename(tmp, path);
|
|
35
51
|
return path;
|
|
36
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* 结算工单:交付物落 `<id>.deliverable.md`(settled=规划产物;failed=诚实
|
|
55
|
+
* 失败说明),工单 json 原子更新 status/settledAt/deliverableFile/error。
|
|
56
|
+
*/
|
|
37
57
|
export async function settleTurnHandoffTicket(stateRoot, ticket, status, deliverable, error) {
|
|
38
58
|
const dir = handoffDir(stateRoot);
|
|
39
|
-
await mkdir(dir, {
|
|
40
|
-
recursive: true
|
|
41
|
-
});
|
|
59
|
+
await mkdir(dir, { recursive: true });
|
|
42
60
|
const deliverablePath = join(dir, `${ticket.id}.deliverable.md`);
|
|
43
61
|
const deliverableTmp = `${deliverablePath}.tmp`;
|
|
44
62
|
await writeFile(deliverableTmp, deliverable, 'utf-8');
|
|
@@ -48,58 +66,56 @@ export async function settleTurnHandoffTicket(stateRoot, ticket, status, deliver
|
|
|
48
66
|
status,
|
|
49
67
|
settledAt: new Date().toISOString(),
|
|
50
68
|
deliverableFile: `${ticket.id}.deliverable.md`,
|
|
51
|
-
...error ? {
|
|
52
|
-
error
|
|
53
|
-
} : {}
|
|
69
|
+
...(error ? { error } : {}),
|
|
54
70
|
};
|
|
55
71
|
const ticketPath = await writeTicketJson(stateRoot, settled);
|
|
56
|
-
return {
|
|
57
|
-
ticketPath,
|
|
58
|
-
deliverablePath
|
|
59
|
-
};
|
|
72
|
+
return { ticketPath, deliverablePath };
|
|
60
73
|
}
|
|
74
|
+
/** 复访查询:按请求时间倒序列出工单;settled 附交付物摘录(≤600 字)。 */
|
|
61
75
|
export async function listTurnHandoffTickets(stateRoot) {
|
|
62
76
|
const dir = handoffDir(stateRoot);
|
|
63
77
|
let names;
|
|
64
78
|
try {
|
|
65
79
|
names = await readdir(dir);
|
|
66
|
-
}
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
67
82
|
return [];
|
|
68
83
|
}
|
|
69
84
|
const views = [];
|
|
70
|
-
for (const name of names){
|
|
71
|
-
if (!name.endsWith('.json'))
|
|
85
|
+
for (const name of names) {
|
|
86
|
+
if (!name.endsWith('.json'))
|
|
87
|
+
continue;
|
|
72
88
|
try {
|
|
73
89
|
const raw = JSON.parse(await readFile(join(dir, name), 'utf-8'));
|
|
74
|
-
if (raw?.schema !== TURN_HANDOFF_SCHEMA)
|
|
90
|
+
if (raw?.schema !== TURN_HANDOFF_SCHEMA)
|
|
91
|
+
continue;
|
|
75
92
|
const view = {
|
|
76
93
|
id: raw.id,
|
|
77
94
|
status: raw.status,
|
|
78
95
|
objective: raw.objective,
|
|
79
96
|
requestedAt: raw.requestedAt,
|
|
80
97
|
etaLabel: raw.etaLabel,
|
|
81
|
-
...raw.settledAt ? {
|
|
82
|
-
|
|
83
|
-
} : {},
|
|
84
|
-
...raw.error ? {
|
|
85
|
-
error: raw.error
|
|
86
|
-
} : {}
|
|
98
|
+
...(raw.settledAt ? { settledAt: raw.settledAt } : {}),
|
|
99
|
+
...(raw.error ? { error: raw.error } : {}),
|
|
87
100
|
};
|
|
88
101
|
if (raw.status !== 'open' && raw.deliverableFile) {
|
|
89
102
|
try {
|
|
90
103
|
const text = await readFile(join(dir, raw.deliverableFile), 'utf-8');
|
|
91
104
|
view.deliverableExcerpt = text.length > 600 ? `${text.slice(0, 600)}…` : text;
|
|
92
|
-
}
|
|
105
|
+
}
|
|
106
|
+
catch { /* 交付物缺失时视图降级,不阻塞列表 */ }
|
|
93
107
|
}
|
|
94
108
|
views.push(view);
|
|
95
|
-
}
|
|
109
|
+
}
|
|
110
|
+
catch { /* 单个坏工单不阻塞列表 */ }
|
|
96
111
|
}
|
|
97
|
-
views.sort((a, b)=>a.requestedAt < b.requestedAt ? 1 : -1);
|
|
112
|
+
views.sort((a, b) => (a.requestedAt < b.requestedAt ? 1 : -1));
|
|
98
113
|
return views;
|
|
99
114
|
}
|
|
100
115
|
function resolveEnvPin(name) {
|
|
101
116
|
const raw = process.env[name];
|
|
102
|
-
if (!raw)
|
|
117
|
+
if (!raw)
|
|
118
|
+
return null;
|
|
103
119
|
const parsed = Number.parseInt(raw, 10);
|
|
104
120
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
105
121
|
}
|
|
@@ -107,16 +123,8 @@ function convergenceContext(code, text) {
|
|
|
107
123
|
return {
|
|
108
124
|
id: randomUUID(),
|
|
109
125
|
role: 'user',
|
|
110
|
-
content: [
|
|
111
|
-
|
|
112
|
-
type: 'text',
|
|
113
|
-
text: `${code}: ${text}`
|
|
114
|
-
}
|
|
115
|
-
],
|
|
116
|
-
source: {
|
|
117
|
-
kind: 'plugin',
|
|
118
|
-
plugin: 'gotry-turn-deadline'
|
|
119
|
-
}
|
|
126
|
+
content: [{ type: 'text', text: `${code}: ${text}` }],
|
|
127
|
+
source: { kind: 'plugin', plugin: 'gotry-turn-deadline' },
|
|
120
128
|
};
|
|
121
129
|
}
|
|
122
130
|
function exhaustionResult(reason) {
|
|
@@ -124,20 +132,10 @@ function exhaustionResult(reason) {
|
|
|
124
132
|
isError: true,
|
|
125
133
|
error: {
|
|
126
134
|
message: reason,
|
|
127
|
-
info: {
|
|
128
|
-
name: 'TurnDeadlineError',
|
|
129
|
-
code: TURN_DEADLINE_EXHAUSTED
|
|
130
|
-
}
|
|
135
|
+
info: { name: 'TurnDeadlineError', code: TURN_DEADLINE_EXHAUSTED },
|
|
131
136
|
},
|
|
132
|
-
content: [
|
|
133
|
-
|
|
134
|
-
type: 'text',
|
|
135
|
-
text: reason
|
|
136
|
-
}
|
|
137
|
-
],
|
|
138
|
-
additionalContexts: [
|
|
139
|
-
convergenceContext(TURN_DEADLINE_EXHAUSTED, 'No more tool dispatches are permitted in this turn. Produce the final answer from existing results.')
|
|
140
|
-
]
|
|
137
|
+
content: [{ type: 'text', text: reason }],
|
|
138
|
+
additionalContexts: [convergenceContext(TURN_DEADLINE_EXHAUSTED, 'No more tool dispatches are permitted in this turn. Produce the final answer from existing results.')],
|
|
141
139
|
};
|
|
142
140
|
}
|
|
143
141
|
function handoffResult(ticket) {
|
|
@@ -146,70 +144,72 @@ function handoffResult(ticket) {
|
|
|
146
144
|
isError: true,
|
|
147
145
|
error: {
|
|
148
146
|
message: `${TURN_DEADLINE_HANDOFF}: sync window exhausted for a deep-planning turn; ticket ${ticket.id}`,
|
|
149
|
-
info: {
|
|
150
|
-
name: 'TurnDeadlineHandoff',
|
|
151
|
-
code: TURN_DEADLINE_HANDOFF
|
|
152
|
-
}
|
|
147
|
+
info: { name: 'TurnDeadlineHandoff', code: TURN_DEADLINE_HANDOFF },
|
|
153
148
|
},
|
|
154
|
-
content: [
|
|
155
|
-
|
|
156
|
-
type: 'text',
|
|
157
|
-
text: `${TURN_DEADLINE_HANDOFF}: ${instruction}`
|
|
158
|
-
}
|
|
159
|
-
],
|
|
160
|
-
additionalContexts: [
|
|
161
|
-
convergenceContext(TURN_DEADLINE_HANDOFF, instruction)
|
|
162
|
-
]
|
|
149
|
+
content: [{ type: 'text', text: `${TURN_DEADLINE_HANDOFF}: ${instruction}` }],
|
|
150
|
+
additionalContexts: [convergenceContext(TURN_DEADLINE_HANDOFF, instruction)],
|
|
163
151
|
};
|
|
164
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* Install the runtime boundary, kept separate from the GoTry tool catalog so
|
|
155
|
+
* the actual Cordis waterfalls can be exercised without booting every tool.
|
|
156
|
+
*/
|
|
165
157
|
export function installTurnDeadline(ctx, options = {}) {
|
|
166
|
-
if (options.enabled === false)
|
|
167
|
-
|
|
168
|
-
|
|
158
|
+
if (options.enabled === false)
|
|
159
|
+
return;
|
|
160
|
+
// Some offline contract tests intentionally provide a registration-only
|
|
161
|
+
// Context slice. They do not drive an agent loop, so there is no boundary
|
|
162
|
+
// to install and no reason to require an event bus.
|
|
163
|
+
if (typeof ctx.on !== 'function')
|
|
164
|
+
return;
|
|
165
|
+
const now = options.now ?? (() => Date.now());
|
|
166
|
+
// Test/benchmark seam only: pin the resolved numbers without touching the
|
|
167
|
+
// routed exit strategy. Product runs never set these.
|
|
169
168
|
const softPin = resolveEnvPin('GOTRY_TURN_DEADLINE_SOFT_MS');
|
|
170
169
|
const hardPin = resolveEnvPin('GOTRY_TURN_DEADLINE_HARD_MS');
|
|
171
170
|
const defaultPolicy = options.fixedPolicy ?? turnPolicyFor('sync-planning');
|
|
172
|
-
const routePolicy = (message)=>{
|
|
173
|
-
if (options.fixedPolicy)
|
|
174
|
-
...options.fixedPolicy
|
|
175
|
-
};
|
|
171
|
+
const routePolicy = (message) => {
|
|
172
|
+
if (options.fixedPolicy)
|
|
173
|
+
return { ...options.fixedPolicy };
|
|
176
174
|
const policy = turnPolicyFor(classifyTurn(message));
|
|
177
|
-
return {
|
|
178
|
-
...policy,
|
|
179
|
-
softMs: softPin ?? policy.softMs,
|
|
180
|
-
hardMs: hardPin ?? policy.hardMs
|
|
181
|
-
};
|
|
175
|
+
return { ...policy, softMs: softPin ?? policy.softMs, hardMs: hardPin ?? policy.hardMs };
|
|
182
176
|
};
|
|
183
177
|
const stateByAgent = new Map();
|
|
184
178
|
const softExecutions = new Map();
|
|
185
179
|
const finalOnlyDisposers = new Map();
|
|
186
|
-
const clearAgent = (agentId)=>{
|
|
180
|
+
const clearAgent = (agentId) => {
|
|
187
181
|
stateByAgent.delete(agentId);
|
|
188
|
-
for (const [token, owner] of softExecutions){
|
|
189
|
-
if (owner.agentId === agentId)
|
|
182
|
+
for (const [token, owner] of softExecutions) {
|
|
183
|
+
if (owner.agentId === agentId)
|
|
184
|
+
softExecutions.delete(token);
|
|
190
185
|
}
|
|
191
186
|
finalOnlyDisposers.get(agentId)?.();
|
|
192
187
|
finalOnlyDisposers.delete(agentId);
|
|
193
188
|
};
|
|
194
|
-
const enterFinalOnly = (agent)=>{
|
|
189
|
+
const enterFinalOnly = (agent) => {
|
|
195
190
|
const agentId = String(agent.id);
|
|
196
|
-
if (finalOnlyDisposers.has(agentId))
|
|
191
|
+
if (finalOnlyDisposers.has(agentId))
|
|
192
|
+
return;
|
|
197
193
|
const globalTools = ctx.tools;
|
|
198
194
|
const scopedTools = agent.ctx?.tools;
|
|
199
195
|
if (typeof globalTools.schemas !== 'function' || typeof scopedTools?.restrict !== 'function') {
|
|
196
|
+
// No registry to suppress: subsequent tool calls in the same turn hit the
|
|
197
|
+
// same per-call denial branch and stay refused until the next turn.
|
|
200
198
|
return;
|
|
201
199
|
}
|
|
202
|
-
const inheritedNames = globalTools.schemas()
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
200
|
+
const inheritedNames = globalTools.schemas()
|
|
201
|
+
.map(schema => schema.name)
|
|
202
|
+
.filter(name => name !== 'run_code');
|
|
203
|
+
if (inheritedNames.length === 0)
|
|
204
|
+
return;
|
|
205
|
+
finalOnlyDisposers.set(agentId, scopedTools.restrict({ deny: inheritedNames }));
|
|
207
206
|
};
|
|
208
|
-
|
|
207
|
+
// 事件主体是 session 对象;agent 归属同一 session 时共用同一预算键。
|
|
208
|
+
const keyOfAgent = (agent) => {
|
|
209
209
|
const session = agent.session;
|
|
210
210
|
return String(session?.id ?? agent.id);
|
|
211
211
|
};
|
|
212
|
-
ctx.on('session/event', (subject, event)=>{
|
|
212
|
+
ctx.on('session/event', (subject, event) => {
|
|
213
213
|
const agentId = String(subject.id);
|
|
214
214
|
if (event.type === 'turn/end') {
|
|
215
215
|
clearAgent(agentId);
|
|
@@ -221,72 +221,66 @@ export function installTurnDeadline(ctx, options = {}) {
|
|
|
221
221
|
if (!stateByAgent.has(agentId)) {
|
|
222
222
|
stateByAgent.set(agentId, {
|
|
223
223
|
startedAt: now(),
|
|
224
|
-
policy: {
|
|
225
|
-
...defaultPolicy,
|
|
226
|
-
softMs: softPin ?? defaultPolicy.softMs,
|
|
227
|
-
hardMs: hardPin ?? defaultPolicy.hardMs
|
|
228
|
-
}
|
|
224
|
+
policy: { ...defaultPolicy, softMs: softPin ?? defaultPolicy.softMs, hardMs: hardPin ?? defaultPolicy.hardMs },
|
|
229
225
|
});
|
|
230
226
|
}
|
|
231
227
|
return;
|
|
232
228
|
}
|
|
233
229
|
if (event.type === 'user/message') {
|
|
230
|
+
// dsh 事件载荷在 event.data 下(benchmark-agent-conformance 同型读法)。
|
|
234
231
|
const message = event.data;
|
|
235
|
-
if (message?.source?.kind !== 'user')
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
});
|
|
232
|
+
if (message?.source?.kind !== 'user')
|
|
233
|
+
return;
|
|
234
|
+
const text = (message.content ?? []).find(block => block.type === 'text')?.text ?? '';
|
|
235
|
+
if (!text.trim())
|
|
236
|
+
return;
|
|
237
|
+
// 每个 user 消息 = 新的预算:路由分类 + 时钟重置。plugin/skill 注入
|
|
238
|
+
// 的 user/message(source.kind !== 'user')不参与路由。
|
|
239
|
+
stateByAgent.set(agentId, { startedAt: now(), policy: routePolicy(text), userMessage: text });
|
|
243
240
|
}
|
|
244
241
|
});
|
|
245
|
-
ctx.on('session/disposed',
|
|
246
|
-
ctx.on('tools/execute', (exec, next)=>{
|
|
247
|
-
|
|
242
|
+
ctx.on('session/disposed', subject => clearAgent(String(subject.id)));
|
|
243
|
+
ctx.on('tools/execute', (exec, next) => {
|
|
244
|
+
// Programmatic/direct calls are not part of a model planner turn.
|
|
245
|
+
if (!exec.agent)
|
|
246
|
+
return next();
|
|
248
247
|
const agentId = keyOfAgent(exec.agent);
|
|
249
|
-
const state = stateByAgent.get(agentId)
|
|
250
|
-
startedAt: now(),
|
|
251
|
-
policy: {
|
|
252
|
-
...defaultPolicy,
|
|
253
|
-
softMs: softPin ?? defaultPolicy.softMs,
|
|
254
|
-
hardMs: hardPin ?? defaultPolicy.hardMs
|
|
255
|
-
}
|
|
256
|
-
};
|
|
248
|
+
const state = stateByAgent.get(agentId)
|
|
249
|
+
?? { startedAt: now(), policy: { ...defaultPolicy, softMs: softPin ?? defaultPolicy.softMs, hardMs: hardPin ?? defaultPolicy.hardMs } };
|
|
257
250
|
stateByAgent.set(agentId, state);
|
|
258
251
|
const elapsed = now() - state.startedAt;
|
|
259
252
|
if (elapsed > state.policy.hardMs) {
|
|
253
|
+
// Synchronous schema suppression so same-step follow-up calls cannot
|
|
254
|
+
// loop on refusal results (the 2026-09-02 trajectory failure).
|
|
260
255
|
enterFinalOnly(exec.agent);
|
|
261
256
|
if (state.policy.exit === 'handoff' && state.userMessage && options.stateRoot) {
|
|
262
|
-
return writeTurnHandoffTicket(options.stateRoot, state.userMessage)
|
|
257
|
+
return writeTurnHandoffTicket(options.stateRoot, state.userMessage)
|
|
258
|
+
.then(ticket => handoffResult(ticket))
|
|
259
|
+
.catch(() => exhaustionResult(`${TURN_DEADLINE_EXHAUSTED}: hard deadline ${state.policy.hardMs}ms reached (ticket persistence failed; degraded to converge)`));
|
|
263
260
|
}
|
|
264
261
|
return Promise.resolve(exhaustionResult(`${TURN_DEADLINE_EXHAUSTED}: turn exceeded hard deadline of ${state.policy.hardMs}ms (elapsed ${elapsed}ms); provide a final answer using existing results`));
|
|
265
262
|
}
|
|
266
263
|
if (elapsed > state.policy.softMs) {
|
|
267
|
-
softExecutions.set(exec.token, {
|
|
268
|
-
agentId,
|
|
269
|
-
exit: state.policy.exit
|
|
270
|
-
});
|
|
264
|
+
softExecutions.set(exec.token, { agentId, exit: state.policy.exit });
|
|
271
265
|
}
|
|
272
266
|
return next();
|
|
273
267
|
});
|
|
274
|
-
ctx.on('tools/post-execute', (exec, _result, next)=>{
|
|
275
|
-
return next().then(
|
|
268
|
+
ctx.on('tools/post-execute', (exec, _result, next) => {
|
|
269
|
+
return next().then(decision => {
|
|
276
270
|
const owner = softExecutions.get(exec.token);
|
|
277
|
-
if (!owner)
|
|
271
|
+
if (!owner)
|
|
272
|
+
return decision;
|
|
278
273
|
softExecutions.delete(exec.token);
|
|
279
|
-
const text = owner.exit === 'handoff'
|
|
274
|
+
const text = owner.exit === 'handoff'
|
|
275
|
+
? 'Turn has crossed the soft deadline of a deep-planning turn. Wrap up context gathering now; the turn will hand off to background planning at the hard deadline.'
|
|
276
|
+
: 'Turn has crossed the soft deadline. Stop dispatching new tools and produce the final answer from gathered evidence.';
|
|
280
277
|
return {
|
|
281
278
|
...decision,
|
|
282
279
|
additionalContexts: [
|
|
283
|
-
...decision.additionalContexts ?? [],
|
|
284
|
-
convergenceContext(TURN_DEADLINE_SOFT, text)
|
|
285
|
-
]
|
|
280
|
+
...(decision.additionalContexts ?? []),
|
|
281
|
+
convergenceContext(TURN_DEADLINE_SOFT, text),
|
|
282
|
+
],
|
|
286
283
|
};
|
|
287
284
|
});
|
|
288
285
|
});
|
|
289
286
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
//# sourceURL=ts/src/turn-deadline.ts
|