@danceiny/gotry 0.0.1-rc.7 → 0.0.1-rc.9
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 +29 -74
- package/bin/gotry-inner.js +50 -1
- package/bin/gotry-stdio-ask.js +59 -0
- package/cordis.gotry-patch.yml +63 -5
- package/data/flights_2026.json +7 -4
- package/data/hotels_2026.json +102 -15
- package/data/time-slot-eval.json +384 -0
- package/data/yunnan-pack.json +2 -1
- package/dist/capabilities/agent-reach-bridge.py +90 -0
- package/dist/capabilities/anything.js +2 -2
- package/dist/capabilities/flyai.js +131 -0
- package/dist/capabilities/hbcli.js +11 -6
- package/dist/capabilities/incident-log.js +2 -1
- package/dist/capabilities/session/action-cache.js +120 -0
- package/dist/capabilities/session/adapters/ctrip-flight.js +83 -0
- package/dist/capabilities/session/adapters/meituan-local.js +73 -0
- package/dist/capabilities/session/extract.js +40 -0
- package/dist/capabilities/session/read-guard.js +56 -0
- package/dist/capabilities/session/transport.js +95 -0
- package/dist/capabilities/session-search.js +95 -0
- package/dist/scripts/action-cache-tests.js +107 -0
- package/dist/scripts/agent-reach-tests.js +1 -1
- package/dist/scripts/agent-reach-wrapper-tests.js +1 -1
- package/dist/scripts/async-collect.js +26 -7
- package/dist/scripts/companion-tests.js +112 -0
- package/dist/scripts/hbcli-tests.js +18 -2
- package/dist/scripts/ledger-tests.js +344 -0
- package/dist/scripts/ledger-workflow-crash.js +42 -0
- package/dist/scripts/memory-capture-tests.js +77 -0
- package/dist/scripts/memory-decay-tests.js +83 -0
- package/dist/scripts/memory-metrics.js +24 -0
- package/dist/scripts/nudge-digest.js +83 -0
- package/dist/scripts/probe-poi-tests.js +9 -0
- package/dist/scripts/replay.js +73 -1
- package/dist/scripts/session-attach-diagnose.js +31 -0
- package/dist/scripts/session-attach-poc.js +65 -0
- package/dist/scripts/session-attach-wait.js +41 -0
- package/dist/scripts/session-extract-tests.js +81 -0
- package/dist/scripts/session-login.js +48 -0
- package/dist/scripts/session-tests.js +162 -0
- package/dist/scripts/skeleton-check.js +3 -1
- package/dist/scripts/skills-contract-tests.js +85 -0
- package/dist/scripts/smoke.js +242 -4
- package/dist/scripts/state-cli-tests.js +136 -0
- package/dist/scripts/state-cli.js +234 -0
- package/dist/scripts/time-eval-tests.js +318 -0
- package/dist/scripts/travel-timeline-tests.js +123 -0
- package/dist/scripts/unified-tests.js +1 -1
- package/dist/src/companions.js +112 -0
- package/dist/src/dsh-llm.js +27 -7
- package/dist/src/index.js +600 -121
- package/dist/src/loop.js +89 -25
- package/dist/src/memory-capture.js +40 -0
- package/dist/src/memory-decay.js +31 -0
- package/dist/src/memory-utility.js +55 -0
- package/dist/src/mock-llm.js +6 -1
- package/dist/src/slot-spec.js +165 -0
- package/dist/src/state-ledger.js +848 -0
- package/dist/src/time-anchor.js +100 -0
- package/dist/src/tool-packet.js +12 -0
- package/dist/src/travel-slots.js +144 -0
- package/dist/src/travel-timeline.js +78 -0
- package/dist/src/unified.js +3 -1
- package/dist/src/wish-pool.js +27 -0
- package/package.json +6 -2
- package/ts/capabilities/hbcli.ts +6 -6
- package/ts/capabilities/incident-log.ts +6 -3
- package/ts/package.json +3 -0
- package/ts/scripts/skeleton-check.ts +5 -1
- package/ts/src/dsh-llm.ts +27 -7
- package/ts/src/index.ts +439 -91
- package/ts/src/loop.ts +109 -34
- package/ts/src/mock-llm.ts +13 -1
- package/ts/src/unified.ts +6 -1
- package/ts/cordis.gotry-patch.yml +0 -36
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
const SENSITIVE_PATTERNS = [
|
|
2
|
+
{
|
|
3
|
+
re: /\d{15,17}[Xx]?/,
|
|
4
|
+
label: '疑似证件号/卡号'
|
|
5
|
+
},
|
|
6
|
+
{
|
|
7
|
+
re: /1[3-9]\d{9}/,
|
|
8
|
+
label: '疑似手机号'
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
re: /(护照|身份证|证件号|通行证)\s*号?\s*[::]?\s*\w+/i,
|
|
12
|
+
label: '证件信息'
|
|
13
|
+
}
|
|
14
|
+
];
|
|
15
|
+
export function sensitiveViolation(text) {
|
|
16
|
+
for (const { re, label } of SENSITIVE_PATTERNS){
|
|
17
|
+
if (re.test(text)) return `负面清单拒收:${label}不入库(需要时由后端从登录态填充)`;
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
export function companionId(label) {
|
|
22
|
+
return label.replace(/\s+/g, '');
|
|
23
|
+
}
|
|
24
|
+
function mergeStrArray(oldArr, newArr) {
|
|
25
|
+
const a = oldArr ?? [];
|
|
26
|
+
let added = false;
|
|
27
|
+
for (const x of newArr ?? []){
|
|
28
|
+
if (!a.includes(x)) {
|
|
29
|
+
a.push(x);
|
|
30
|
+
added = true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
merged: a,
|
|
35
|
+
added
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export function upsertCompanion(profiles, patch) {
|
|
39
|
+
if (!patch.label?.trim()) return {
|
|
40
|
+
profiles,
|
|
41
|
+
appended: false,
|
|
42
|
+
companionId: '',
|
|
43
|
+
reason: 'label 必填'
|
|
44
|
+
};
|
|
45
|
+
const violation = sensitiveViolation(JSON.stringify(patch));
|
|
46
|
+
if (violation) return {
|
|
47
|
+
profiles,
|
|
48
|
+
appended: false,
|
|
49
|
+
companionId: '',
|
|
50
|
+
reason: violation
|
|
51
|
+
};
|
|
52
|
+
const id = companionId(patch.label);
|
|
53
|
+
const existing = profiles.find((p)=>p.companion_id === id);
|
|
54
|
+
if (!existing) {
|
|
55
|
+
const full = {
|
|
56
|
+
schema: 'companion_profile.v1',
|
|
57
|
+
companion_id: id,
|
|
58
|
+
label: patch.label.trim(),
|
|
59
|
+
constraints: {
|
|
60
|
+
mobility: patch.constraints.mobility,
|
|
61
|
+
health: patch.constraints.health ? [
|
|
62
|
+
...patch.constraints.health
|
|
63
|
+
] : undefined,
|
|
64
|
+
prefs: patch.constraints.prefs ? [
|
|
65
|
+
...patch.constraints.prefs
|
|
66
|
+
] : undefined
|
|
67
|
+
},
|
|
68
|
+
evidence: [
|
|
69
|
+
patch.evidence
|
|
70
|
+
],
|
|
71
|
+
ts: new Date().toISOString()
|
|
72
|
+
};
|
|
73
|
+
return {
|
|
74
|
+
profiles: [
|
|
75
|
+
...profiles,
|
|
76
|
+
full
|
|
77
|
+
],
|
|
78
|
+
appended: true,
|
|
79
|
+
companionId: id
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const mergedConstraints = {
|
|
83
|
+
mobility: patch.constraints.mobility ?? existing.constraints.mobility,
|
|
84
|
+
health: mergeStrArray(existing.constraints.health, patch.constraints.health).merged,
|
|
85
|
+
prefs: mergeStrArray(existing.constraints.prefs, patch.constraints.prefs).merged
|
|
86
|
+
};
|
|
87
|
+
const ev = mergeStrArray(existing.evidence, [
|
|
88
|
+
patch.evidence
|
|
89
|
+
]);
|
|
90
|
+
const healthLen = mergedConstraints.health?.length ?? 0;
|
|
91
|
+
const prefsLen = mergedConstraints.prefs?.length ?? 0;
|
|
92
|
+
const changed = mergedConstraints.mobility !== existing.constraints.mobility || healthLen !== (existing.constraints.health?.length ?? 0) || prefsLen !== (existing.constraints.prefs?.length ?? 0) || ev.added;
|
|
93
|
+
if (!changed) return {
|
|
94
|
+
profiles,
|
|
95
|
+
appended: false,
|
|
96
|
+
companionId: id
|
|
97
|
+
};
|
|
98
|
+
const next = profiles.map((p)=>p.companion_id === id ? {
|
|
99
|
+
...p,
|
|
100
|
+
constraints: mergedConstraints,
|
|
101
|
+
evidence: ev.merged,
|
|
102
|
+
ts: new Date().toISOString()
|
|
103
|
+
} : p);
|
|
104
|
+
return {
|
|
105
|
+
profiles: next,
|
|
106
|
+
appended: true,
|
|
107
|
+
companionId: id
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
//# sourceURL=/Users/bytedance/work/gotry/ts/src/companions.ts
|
package/dist/src/dsh-llm.js
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import { parseFlightPackToSpec } from './unified.js';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import { buildTimeAnchor } from './time-anchor.js';
|
|
3
|
+
import { buildSlotSystem, flagExpiredSlots, normalizeExtraction } from './travel-slots.js';
|
|
4
|
+
const model = ()=>process.env['LLM_MODEL'] ?? process.env['DEEPSEEK_MODEL'] ?? 'MiniMax-M2';
|
|
5
|
+
const base = ()=>(process.env['LLM_BASE_URL'] ?? process.env['DEEPSEEK_BASE_URL'] ?? 'https://api.minimax.io/v1').replace(/\/$/, '');
|
|
4
6
|
async function chat(messages, json) {
|
|
5
7
|
const key = process.env['LLM_API_KEY'] ?? process.env['DEEPSEEK_API_KEY'];
|
|
6
8
|
if (!key) throw new Error('LLM_API_KEY 未设置(兼容 DEEPSEEK_API_KEY 别名)——真 LLM 路径不可用,请回退 mock(ADR-8)');
|
|
7
|
-
const res = await fetch(`${
|
|
9
|
+
const res = await fetch(`${base()}/chat/completions`, {
|
|
8
10
|
method: 'POST',
|
|
9
11
|
headers: {
|
|
10
12
|
'Content-Type': 'application/json',
|
|
11
13
|
Authorization: `Bearer ${key}`
|
|
12
14
|
},
|
|
13
15
|
body: JSON.stringify({
|
|
14
|
-
model:
|
|
16
|
+
model: model(),
|
|
15
17
|
messages,
|
|
16
18
|
...json ? {
|
|
17
19
|
response_format: {
|
|
@@ -46,9 +48,10 @@ const SKELETON_SYSTEM = `你是行程骨架抽取器。从对话中抽取行程
|
|
|
46
48
|
输出 JSON:{"scenario":"erhai|workation|yunnan|generic","segments":[{"id":"f1","role":"choice|fixed","route":"HKG->HKT","dateHint":"2026-07-18","anchors":{"arriveByMin":885}}]}
|
|
47
49
|
规则:每个跨城移动一段;锚点只放用户明说或必然的(如"当天到"→arriveByMin 23:59=1439);时刻用当日分钟。
|
|
48
50
|
scenario 判定:「洱海/大理/千岛湖/太湖+选目的地」→erhai(候选集);「普吉/workation/远程办公+多城链」→workation(五段链);「云南/大理丽江」→yunnan;不确定→generic。只输出 JSON。`;
|
|
49
|
-
export function createOpenAICompatLlm(flightPackPath) {
|
|
51
|
+
export function createOpenAICompatLlm(flightPackPath, clock = ()=>new Date()) {
|
|
50
52
|
const pack = flightPackPath;
|
|
51
53
|
const historyText = (h)=>h.map((t)=>`${t.role === 'user' ? '用户' : '助手'}: ${t.text}`).join('\n');
|
|
54
|
+
const anchorContext = ()=>`时间锚点卡:\n${buildTimeAnchor(clock()).card}`;
|
|
52
55
|
return {
|
|
53
56
|
async extractFacts (history) {
|
|
54
57
|
const out = await chat([
|
|
@@ -58,7 +61,7 @@ export function createOpenAICompatLlm(flightPackPath) {
|
|
|
58
61
|
},
|
|
59
62
|
{
|
|
60
63
|
role: 'user',
|
|
61
|
-
content: historyText(history)
|
|
64
|
+
content: `${anchorContext()}\n\n${historyText(history)}`
|
|
62
65
|
}
|
|
63
66
|
], true);
|
|
64
67
|
const obj = parseJsonBlock(out);
|
|
@@ -78,7 +81,7 @@ export function createOpenAICompatLlm(flightPackPath) {
|
|
|
78
81
|
};
|
|
79
82
|
},
|
|
80
83
|
async extractSpec (history, state) {
|
|
81
|
-
const context =
|
|
84
|
+
const context = `${anchorContext()}\n已断言日历:${JSON.stringify(state.calendar.assertedWeekdays)}\nprofile:${JSON.stringify(state.profile)}`;
|
|
82
85
|
const out = await chat([
|
|
83
86
|
{
|
|
84
87
|
role: 'system',
|
|
@@ -134,6 +137,23 @@ export function createOpenAICompatLlm(flightPackPath) {
|
|
|
134
137
|
packSpec.budgetCny = 9000;
|
|
135
138
|
return packSpec;
|
|
136
139
|
},
|
|
140
|
+
async extractSlots (history, now) {
|
|
141
|
+
const anchor = buildTimeAnchor(now ?? clock());
|
|
142
|
+
const out = await chat([
|
|
143
|
+
{
|
|
144
|
+
role: 'system',
|
|
145
|
+
content: buildSlotSystem(anchor)
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
role: 'user',
|
|
149
|
+
content: historyText(history)
|
|
150
|
+
}
|
|
151
|
+
], true);
|
|
152
|
+
const obj = parseJsonBlock(out);
|
|
153
|
+
if (!obj) return null;
|
|
154
|
+
const ext = normalizeExtraction(obj, history.map((t)=>t.text).join('\n'));
|
|
155
|
+
return ext ? flagExpiredSlots(ext, anchor) : null;
|
|
156
|
+
},
|
|
137
157
|
async polishQuestion (q) {
|
|
138
158
|
const out = await chat([
|
|
139
159
|
{
|