luckytri 1.3.0 → 1.3.3
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/docs/en/CHANGELOG.md +16 -0
- package/docs/zh/CHANGELOG.md +16 -0
- package/package.json +1 -1
- package/public/guide.en.html +3 -3
- package/public/guide.html +3 -3
- package/server/core/conversation-grounding.js +216 -1
- package/server/core/conversation-needs.js +10 -3
- package/server/core/dialogue-context.js +171 -26
- package/server/core/dialogue-contract.js +2 -2
- package/server/core/message-scheduler.js +13 -10
- package/server/core/reply-delivery.js +35 -15
- package/server/core/response-validator.js +1 -1
- package/server/core/turn-processor.js +2 -0
- package/server/core/turn.js +20 -1
- package/server/core/understanding.js +60 -4
- package/server/core/vision-manager.js +76 -7
- package/server/i18n/decisions.js +10 -5
- package/server/i18n/errors.js +2 -0
- package/server/mind/guard.js +88 -68
- package/server/mind/relationship-context.js +110 -71
- package/server/mind/time/sharing.js +582 -482
- package/server/mind/time/works.js +51 -48
- package/server/runtime/update-manager.js +34 -2
- package/server/stickers/offer.js +44 -15
|
@@ -1,71 +1,110 @@
|
|
|
1
|
-
// Current relationship facts and the words she once used about them have
|
|
2
|
-
// different jobs. Keep history intact, and make that distinction at recall.
|
|
3
|
-
export const RELATIONSHIP_KNOWLEDGE_RULE =
|
|
4
|
-
"relationships.known 是当前已知的人际关系,属于同一个自己的生活。旧经历、自我线索中的否认或玩笑保留为当时的看法,不据此否定新关系记录。知道对方是谁与对方是什么关系,和自己的感受、信任、称呼选择分开;不机械扮演,不编造共同过去或对方的同意。";
|
|
5
|
-
|
|
6
|
-
export function mentionsRelationship(content, relation) {
|
|
7
|
-
const words = String(content || "").toLocaleLowerCase();
|
|
8
|
-
return [
|
|
9
|
-
relation.name,
|
|
10
|
-
...(relation.knownAs || []),
|
|
11
|
-
relation.peerRole,
|
|
12
|
-
relation.selfRole,
|
|
13
|
-
]
|
|
14
|
-
.filter(Boolean)
|
|
15
|
-
.some((word) => {
|
|
16
|
-
const escaped = String(word).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
17
|
-
const boundary = /^[\w .-]+$/.test(word);
|
|
18
|
-
return new RegExp(
|
|
19
|
-
boundary ? `(?<![\\w])${escaped}(?![\\w])` : escaped,
|
|
20
|
-
"i",
|
|
21
|
-
).test(words);
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function relationshipHistory(content, created, knowledge) {
|
|
26
|
-
return (knowledge?.known || []).some(
|
|
27
|
-
(r) =>
|
|
28
|
-
Number.isFinite(created) &&
|
|
29
|
-
created < r.created &&
|
|
30
|
-
mentionsRelationship(content, r),
|
|
31
|
-
)
|
|
32
|
-
? `${content}(关系记录更新前的看法;保留当时的感受,不据此否定当前关系事实)`
|
|
33
|
-
: content;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
1
|
+
// Current relationship facts and the words she once used about them have
|
|
2
|
+
// different jobs. Keep history intact, and make that distinction at recall.
|
|
3
|
+
export const RELATIONSHIP_KNOWLEDGE_RULE =
|
|
4
|
+
"relationships.known 是当前已知的人际关系,属于同一个自己的生活。旧经历、自我线索中的否认或玩笑保留为当时的看法,不据此否定新关系记录。知道对方是谁与对方是什么关系,和自己的感受、信任、称呼选择分开;不机械扮演,不编造共同过去或对方的同意。";
|
|
5
|
+
|
|
6
|
+
export function mentionsRelationship(content, relation) {
|
|
7
|
+
const words = String(content || "").toLocaleLowerCase();
|
|
8
|
+
return [
|
|
9
|
+
relation.name,
|
|
10
|
+
...(relation.knownAs || []),
|
|
11
|
+
relation.peerRole,
|
|
12
|
+
relation.selfRole,
|
|
13
|
+
]
|
|
14
|
+
.filter(Boolean)
|
|
15
|
+
.some((word) => {
|
|
16
|
+
const escaped = String(word).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
17
|
+
const boundary = /^[\w .-]+$/.test(word);
|
|
18
|
+
return new RegExp(
|
|
19
|
+
boundary ? `(?<![\\w])${escaped}(?![\\w])` : escaped,
|
|
20
|
+
"i",
|
|
21
|
+
).test(words);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function relationshipHistory(content, created, knowledge) {
|
|
26
|
+
return (knowledge?.known || []).some(
|
|
27
|
+
(r) =>
|
|
28
|
+
Number.isFinite(created) &&
|
|
29
|
+
created < r.created &&
|
|
30
|
+
mentionsRelationship(content, r),
|
|
31
|
+
)
|
|
32
|
+
? `${content}(关系记录更新前的看法;保留当时的感受,不据此否定当前关系事实)`
|
|
33
|
+
: content;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const KINSHIP =
|
|
37
|
+
/姐|妹|哥|弟|父|母|女儿|爸|妈|亲戚|Maker|女儿/;
|
|
38
|
+
|
|
39
|
+
// Banter that treats a registered open kinship as something to deny out loud
|
|
40
|
+
// ("谁跟你姐妹", "谁跟你亲戚"). Tone may still tease; the registered fact
|
|
41
|
+
// itself is not up for denial.
|
|
42
|
+
const KINSHIP_DENIAL =
|
|
43
|
+
/(?:谁跟你|什么).{0,6}(?:姐妹|亲戚)|不是姐妹|没(?:有)?姐妹|不认.{0,8}(?:妹妹|姐姐|姐妹|亲戚)|少来.{0,16}(?:姐妹|亲戚)|关你屁事.{0,12}(?:户口|亲戚|姐妹)/;
|
|
44
|
+
|
|
45
|
+
// Narrow, literal factual denials only. Disagreement with a label, old words,
|
|
46
|
+
// fictional dialogue and feelings are left to the contextual reviewer.
|
|
47
|
+
export function relationshipClaimIssues(bubbles, knowledge) {
|
|
48
|
+
const issues = [];
|
|
49
|
+
const known = (knowledge?.known || []).filter(
|
|
50
|
+
(r) => !r.discretion || r.discretion === "open",
|
|
51
|
+
);
|
|
52
|
+
for (const r of known) {
|
|
53
|
+
const role = String(r.peerRole || "").replace(
|
|
54
|
+
/[.*+?^${}()|[\]\\]/g,
|
|
55
|
+
"\\$&",
|
|
56
|
+
);
|
|
57
|
+
const selfRole = String(r.selfRole || "");
|
|
58
|
+
const names = [r.name, ...(r.knownAs || [])].filter(Boolean);
|
|
59
|
+
const kinship = KINSHIP.test(r.peerRole || "") || KINSHIP.test(selfRole);
|
|
60
|
+
for (const line of bubbles || []) {
|
|
61
|
+
for (const clause of String(line).split(/[,,。!?!?;;\n]/)) {
|
|
62
|
+
if (
|
|
63
|
+
/以前|之前|当时|过去|曾经|从前|一开始|原来|小说|台词|[“「"『]/.test(
|
|
64
|
+
clause,
|
|
65
|
+
)
|
|
66
|
+
)
|
|
67
|
+
continue;
|
|
68
|
+
const namedDenial = names.some((name) => {
|
|
69
|
+
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
70
|
+
return new RegExp(
|
|
71
|
+
`(?:^|[\\s::])${escaped}(?:也|本来|根本)?(?:不是|并非)我(?:的)?${role}(?:$|[\\s,。])|我(?:并)?不认识\\s*${escaped}(?:$|[\\s,。])`,
|
|
72
|
+
"i",
|
|
73
|
+
).test(clause);
|
|
74
|
+
});
|
|
75
|
+
const absentRole = role
|
|
76
|
+
? new RegExp(
|
|
77
|
+
`我(?:本来|本来也|现在|根本|一直|从来)?(?:就|也)?(?:没有|没)${role}(?:$|[\\s,。])`,
|
|
78
|
+
).test(clause)
|
|
79
|
+
: false;
|
|
80
|
+
const banterDenial = kinship && KINSHIP_DENIAL.test(clause);
|
|
81
|
+
if (namedDenial || absentRole || banterDenial) {
|
|
82
|
+
issues.push(
|
|
83
|
+
`当前已知 ${r.name || r.subjectId} 与自己的关系是 ${r.peerRole || r.selfRole},不能把旧印象当成关系不存在;可保留自己的感受和称呼选择,按当前记录核对再说`,
|
|
84
|
+
);
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return [...new Set(issues)];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Summaries that narrate "认亲被拒" teach her to deny open kinship again.
|
|
94
|
+
// Soften that pattern when open family roles are on record; do not delete facts.
|
|
95
|
+
export function softenRelationDenialSummaries(summaries, knowledge) {
|
|
96
|
+
const openKin = (knowledge?.known || []).some(
|
|
97
|
+
(r) =>
|
|
98
|
+
(!r.discretion || r.discretion === "open") &&
|
|
99
|
+
(KINSHIP.test(r.peerRole || "") || KINSHIP.test(r.selfRole || "")),
|
|
100
|
+
);
|
|
101
|
+
if (!openKin || !Array.isArray(summaries)) return summaries || [];
|
|
102
|
+
return summaries.map((row) => {
|
|
103
|
+
if (!row || typeof row.summary !== "string") return row;
|
|
104
|
+
const summary = row.summary.replace(
|
|
105
|
+
/认亲被拒[^。;]*/g,
|
|
106
|
+
"姐妹关系仍在,偶尔玩笑推搪",
|
|
107
|
+
);
|
|
108
|
+
return summary === row.summary ? row : { ...row, summary };
|
|
109
|
+
});
|
|
110
|
+
}
|