luckytri 1.0.0

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.
Files changed (235) hide show
  1. package/.github/SECURITY.md +71 -0
  2. package/LICENSE +21 -0
  3. package/README.en.md +250 -0
  4. package/README.md +250 -0
  5. package/bin/luckytri.js +107 -0
  6. package/docs/brand/banner.png +0 -0
  7. package/docs/brand/palette.png +0 -0
  8. package/docs/brand/portrait.png +0 -0
  9. package/docs/en/CHANGELOG.md +113 -0
  10. package/docs/en/architecture.md +152 -0
  11. package/docs/en/chat-style.md +62 -0
  12. package/docs/en/connect.md +63 -0
  13. package/docs/en/guide.md +216 -0
  14. package/docs/en/her-life.md +189 -0
  15. package/docs/en/npm-release.md +25 -0
  16. package/docs/en/plugins.md +82 -0
  17. package/docs/en/recovery.md +28 -0
  18. package/docs/en/time.md +71 -0
  19. package/docs/en/webui.md +73 -0
  20. package/docs/zh/CHANGELOG.md +113 -0
  21. package/docs/zh/architecture.md +152 -0
  22. package/docs/zh/chat-style.md +62 -0
  23. package/docs/zh/connect.md +63 -0
  24. package/docs/zh/guide.md +216 -0
  25. package/docs/zh/her-life.md +189 -0
  26. package/docs/zh/npm-release.md +33 -0
  27. package/docs/zh/plugins.md +82 -0
  28. package/docs/zh/recovery.md +28 -0
  29. package/docs/zh/time.md +71 -0
  30. package/docs/zh/webui.md +73 -0
  31. package/package.json +108 -0
  32. package/plugins/sdk/index.d.ts +155 -0
  33. package/plugins/sdk/testing.js +58 -0
  34. package/plugins/weather/index.js +82 -0
  35. package/plugins/weather/luckytri-plugin.json +29 -0
  36. package/public/app/assets/ChatsPage-C-FcRapR.js +3 -0
  37. package/public/app/assets/ChatsPage-DfyPCS9N.css +1 -0
  38. package/public/app/assets/Empty-CpP5kQHH.js +2 -0
  39. package/public/app/assets/Empty-DmUB2-Bk.css +1 -0
  40. package/public/app/assets/Field-D4gY-INU.js +1 -0
  41. package/public/app/assets/HeartPage-Bft9wZp5.css +1 -0
  42. package/public/app/assets/HeartPage-CPy_thQd.js +1 -0
  43. package/public/app/assets/LifePage-BUi5euBF.css +1 -0
  44. package/public/app/assets/LifePage-CxWvwmSf.js +1 -0
  45. package/public/app/assets/MemoryPage-DC4rhQ68.js +1 -0
  46. package/public/app/assets/MemoryPage-cZvXfkXb.css +1 -0
  47. package/public/app/assets/NaturePage-CTXHCE2D.css +1 -0
  48. package/public/app/assets/NaturePage-IvYw04Zq.js +3 -0
  49. package/public/app/assets/PeoplePage-BmUxkrOU.css +1 -0
  50. package/public/app/assets/PeoplePage-Cqefm9-q.js +1 -0
  51. package/public/app/assets/PluginsPage-DKSaKvXb.js +2 -0
  52. package/public/app/assets/PluginsPage-HyBe5D8w.css +1 -0
  53. package/public/app/assets/SystemPage-CAMPoYqM.css +1 -0
  54. package/public/app/assets/SystemPage-CJmtJkrK.js +1 -0
  55. package/public/app/assets/TimePage-BOms_n4I.css +1 -0
  56. package/public/app/assets/TimePage-Cw44inM4.js +3 -0
  57. package/public/app/assets/formatters-ZmW_xFHw.js +1 -0
  58. package/public/app/assets/index-BheRW-1t.js +4 -0
  59. package/public/app/assets/index-YDz1ree1.css +1 -0
  60. package/public/app/assets/knowledge-DG0e0uKw.js +1 -0
  61. package/public/app/assets/liquid-garden-IMoHBwzc.png +0 -0
  62. package/public/app/assets/luckytri-home-95QKeMtc.png +0 -0
  63. package/public/app/assets/media-BzPDBm7e.js +1 -0
  64. package/public/app/index.html +27 -0
  65. package/public/guide.en.html +1053 -0
  66. package/public/guide.html +893 -0
  67. package/public/plugin-kit/v1/bridge.js +30 -0
  68. package/public/plugin-kit/v1/kit.css +14 -0
  69. package/public/tutorial.en.md +214 -0
  70. package/public/tutorial.md +214 -0
  71. package/scripts/backup.js +311 -0
  72. package/scripts/browser.js +41 -0
  73. package/scripts/launch.js +94 -0
  74. package/scripts/plugin.js +150 -0
  75. package/scripts/proxy-config.js +167 -0
  76. package/scripts/recover.js +26 -0
  77. package/scripts/runtime.js +25 -0
  78. package/scripts/service.js +47 -0
  79. package/scripts/setup.js +50 -0
  80. package/scripts/start-server.js +41 -0
  81. package/scripts/stop.js +36 -0
  82. package/server/app.js +96 -0
  83. package/server/channels/adapters.js +27 -0
  84. package/server/channels/contract.js +57 -0
  85. package/server/channels/hub.js +165 -0
  86. package/server/channels/index.js +25 -0
  87. package/server/channels/onebot/adapter.js +288 -0
  88. package/server/channels/onebot/index.js +336 -0
  89. package/server/channels/onebot/token.js +3 -0
  90. package/server/channels/qqbot/adapter.js +253 -0
  91. package/server/channels/qqbot/api.js +199 -0
  92. package/server/channels/qqbot/credentials.js +11 -0
  93. package/server/channels/qqbot/gateway.js +274 -0
  94. package/server/channels/qqbot/index.js +389 -0
  95. package/server/channels/segments.js +40 -0
  96. package/server/channels/session-key.js +153 -0
  97. package/server/channels/state.js +42 -0
  98. package/server/core/api.js +564 -0
  99. package/server/core/capabilities.js +208 -0
  100. package/server/core/context-builder.js +288 -0
  101. package/server/core/context-compactor.js +454 -0
  102. package/server/core/conversation-cues.js +325 -0
  103. package/server/core/conversation-manager.js +87 -0
  104. package/server/core/events.js +60 -0
  105. package/server/core/feedback.js +8 -0
  106. package/server/core/group-style.js +72 -0
  107. package/server/core/image-preprocessor.js +208 -0
  108. package/server/core/initiative-context.js +66 -0
  109. package/server/core/input-budget.js +32 -0
  110. package/server/core/local-demo.js +98 -0
  111. package/server/core/message-manager.js +118 -0
  112. package/server/core/message-scheduler.js +78 -0
  113. package/server/core/model-json.js +190 -0
  114. package/server/core/model-manager.js +1213 -0
  115. package/server/core/model-presets.js +900 -0
  116. package/server/core/name-call.js +29 -0
  117. package/server/core/net-guard.js +49 -0
  118. package/server/core/network.js +157 -0
  119. package/server/core/orchestrator.js +569 -0
  120. package/server/core/perceivers.js +91 -0
  121. package/server/core/person-name.js +22 -0
  122. package/server/core/persona-manager.js +243 -0
  123. package/server/core/reply-delivery.js +393 -0
  124. package/server/core/reply-target-resolver.js +50 -0
  125. package/server/core/repository.js +293 -0
  126. package/server/core/response-generator.js +50 -0
  127. package/server/core/response-validator.js +508 -0
  128. package/server/core/retired-prompts.js +51 -0
  129. package/server/core/sessions.js +109 -0
  130. package/server/core/speaker-names.js +92 -0
  131. package/server/core/topic-tracker.js +65 -0
  132. package/server/core/turn-processor.js +630 -0
  133. package/server/core/turn.js +236 -0
  134. package/server/core/vision-manager.js +633 -0
  135. package/server/http.js +18 -0
  136. package/server/i18n/decisions.js +206 -0
  137. package/server/i18n/errors.js +497 -0
  138. package/server/i18n/index.js +144 -0
  139. package/server/i18n/labels.js +653 -0
  140. package/server/i18n/models.js +111 -0
  141. package/server/index.js +102 -0
  142. package/server/knowledge/api.js +342 -0
  143. package/server/knowledge/embedding-profile.js +114 -0
  144. package/server/knowledge/index.js +13 -0
  145. package/server/knowledge/manager.js +386 -0
  146. package/server/knowledge/retrieval.js +93 -0
  147. package/server/knowledge/schema.js +154 -0
  148. package/server/knowledge/vector-index.js +90 -0
  149. package/server/mind/affect.js +265 -0
  150. package/server/mind/anticipations.js +507 -0
  151. package/server/mind/api.js +703 -0
  152. package/server/mind/attention.js +200 -0
  153. package/server/mind/bonds.js +558 -0
  154. package/server/mind/budget.js +152 -0
  155. package/server/mind/clock.js +83 -0
  156. package/server/mind/context-selection.js +61 -0
  157. package/server/mind/continuity.js +562 -0
  158. package/server/mind/conversation-origin.js +175 -0
  159. package/server/mind/day-planner.js +324 -0
  160. package/server/mind/days.js +210 -0
  161. package/server/mind/evidence-read.js +45 -0
  162. package/server/mind/evidence.js +148 -0
  163. package/server/mind/faces.js +138 -0
  164. package/server/mind/guard.js +60 -0
  165. package/server/mind/index.js +445 -0
  166. package/server/mind/initiative.js +333 -0
  167. package/server/mind/life/activities.js +21 -0
  168. package/server/mind/life/context.js +309 -0
  169. package/server/mind/life/diary.js +786 -0
  170. package/server/mind/life/growth.js +252 -0
  171. package/server/mind/life/index.js +1049 -0
  172. package/server/mind/life/presence.js +305 -0
  173. package/server/mind/meetings.js +1069 -0
  174. package/server/mind/memory-policy.js +48 -0
  175. package/server/mind/memory.js +888 -0
  176. package/server/mind/nature.js +262 -0
  177. package/server/mind/novelty.js +19 -0
  178. package/server/mind/observations.js +84 -0
  179. package/server/mind/own-day.js +324 -0
  180. package/server/mind/own-voice.js +318 -0
  181. package/server/mind/periods.js +118 -0
  182. package/server/mind/reading.js +120 -0
  183. package/server/mind/salience.js +201 -0
  184. package/server/mind/schema.js +562 -0
  185. package/server/mind/self.js +484 -0
  186. package/server/mind/senses.js +53 -0
  187. package/server/mind/thoughts.js +274 -0
  188. package/server/mind/time/activity-clock.js +196 -0
  189. package/server/mind/time/agenda.js +242 -0
  190. package/server/mind/time/api.js +200 -0
  191. package/server/mind/time/attention.js +34 -0
  192. package/server/mind/time/availability.js +69 -0
  193. package/server/mind/time/commitment-review.js +198 -0
  194. package/server/mind/time/delivery-links.js +130 -0
  195. package/server/mind/time/executor.js +512 -0
  196. package/server/mind/time/experiences.js +128 -0
  197. package/server/mind/time/games.js +562 -0
  198. package/server/mind/time/index.js +739 -0
  199. package/server/mind/time/intent.js +166 -0
  200. package/server/mind/time/kinds.js +171 -0
  201. package/server/mind/time/model-material.js +77 -0
  202. package/server/mind/time/plugin-activity.js +207 -0
  203. package/server/mind/time/presentation.js +51 -0
  204. package/server/mind/time/schedule.js +83 -0
  205. package/server/mind/time/schema.js +84 -0
  206. package/server/mind/time/search.js +383 -0
  207. package/server/mind/time/sharing.js +472 -0
  208. package/server/mind/time/task-links.js +311 -0
  209. package/server/mind/time/tasks.js +587 -0
  210. package/server/mind/time/works.js +432 -0
  211. package/server/mind/traits.js +191 -0
  212. package/server/mind/util.js +110 -0
  213. package/server/mind/view.js +273 -0
  214. package/server/paths.js +102 -0
  215. package/server/plugins/api.js +204 -0
  216. package/server/plugins/host.js +967 -0
  217. package/server/plugins/install.js +295 -0
  218. package/server/plugins/manifest.js +201 -0
  219. package/server/plugins/permissions.js +42 -0
  220. package/server/plugins/runner/guard.mjs +36 -0
  221. package/server/plugins/runner/worker.mjs +250 -0
  222. package/server/plugins/schema.js +91 -0
  223. package/server/plugins/zip.js +112 -0
  224. package/server/startup-lock.js +118 -0
  225. package/server/storage/archive.js +241 -0
  226. package/server/storage/backup-cleanup-worker.js +8 -0
  227. package/server/storage/backup-cleanup.js +414 -0
  228. package/server/storage/backup-lock.js +76 -0
  229. package/server/storage/backup-scheduler.js +131 -0
  230. package/server/storage/store.js +199 -0
  231. package/server/studio/display-names.js +138 -0
  232. package/server/studio/management.js +102 -0
  233. package/server/studio/readiness.js +190 -0
  234. package/server/studio/settings.js +236 -0
  235. package/server/version.js +10 -0
@@ -0,0 +1,201 @@
1
+ import { interestTerms, namesProject } from "./attention.js";
2
+ import { similar } from "./util.js";
3
+
4
+ // How long each kind of thing stays with her without being lived again, as
5
+ // a half-life in days she actually lived. Nothing here is deleted: a faded
6
+ // thread is only out of view until something touches it again.
7
+ export const THREAD_HALF_LIFE = {
8
+ trait: 180,
9
+ view: 90,
10
+ habit: 90,
11
+ interest: 60,
12
+ care: 30,
13
+ intention: 30,
14
+ curiosity: 21,
15
+ };
16
+ export const THOUGHT_HALF_LIFE = {
17
+ unfinished: 21,
18
+ revision: 14,
19
+ reflection: 10,
20
+ reconnection: 10,
21
+ };
22
+ const THREAD_GRACE = 3;
23
+ export const THREAD_FADED = 0.12;
24
+ export const THREAD_FADING = 0.2;
25
+ export const THOUGHT_FADED = 0.1;
26
+ // A meeting's meaning stays about as long as an unfinished thought. It is
27
+ // not deleted; it only leaves what she is looking at now.
28
+ export const MEETING_HALF_LIFE = 21;
29
+ export const MEETING_FADED = 0.12;
30
+ // A memory nobody has touched in this many lived days needs a strong cue.
31
+ export const MEMORY_IDLE_DAYS = 45;
32
+ // The strongest threads stay with her however quiet it gets.
33
+ export const CORE_THREADS = 2;
34
+
35
+ const round = (value) => Math.round(value * 1000) / 1000;
36
+
37
+ // An opinion the nightly memory step picked out of one chat is not yet who she
38
+ // is. It stays only as long as it keeps coming back: each new piece of
39
+ // evidence renews it, and one that never recurs fades like a passing thought.
40
+ export const PASSING_VIEW_HALF_LIFE = 21;
41
+
42
+ export function threadSalience(row, lived) {
43
+ const idle = lived.since(row.created);
44
+ const settled = row.kind === "trait" && (row.days?.length || 0) >= 5 ? 2 : 1;
45
+ const passing = row.kind === "view" && row.origin === "memory";
46
+ const half = passing
47
+ ? PASSING_VIEW_HALF_LIFE
48
+ : (THREAD_HALF_LIFE[row.kind] || 60) * settled;
49
+ return round(
50
+ Number(row.strength || 0) *
51
+ 0.5 ** (Math.max(0, idle - THREAD_GRACE) / half),
52
+ );
53
+ }
54
+
55
+ // A revisit that has come due brings a thought back for a while.
56
+ export function thoughtSalience(thought, lived, now) {
57
+ const due = !!(thought.revisit_at && thought.revisit_at <= now);
58
+ const from = due
59
+ ? Math.max(thought.created, thought.revisit_at)
60
+ : thought.created;
61
+ const base = due
62
+ ? Math.max(0.6, Number(thought.importance || 0))
63
+ : Number(thought.importance || 0);
64
+ return round(
65
+ base * 0.5 ** (lived.since(from) / (THOUGHT_HALF_LIFE[thought.kind] || 14)),
66
+ );
67
+ }
68
+
69
+ export function meetingSalience(created, lived) {
70
+ return round(0.5 ** (lived.since(created) / MEETING_HALF_LIFE));
71
+ }
72
+
73
+ // Whether what is being said touches this content: two shared word pairs,
74
+ // so one common pair is not enough to bring something back.
75
+ export function touches(content, cue, need = 2) {
76
+ if (!cue?.size) return false;
77
+ let shared = 0;
78
+ for (const term of interestTerms([content]))
79
+ if (cue.has(term) && ++shared >= need) return true;
80
+ return false;
81
+ }
82
+
83
+ // Whether this wording is still her sentence: two distinctive pairs in common
84
+ // with what was said, or one when the wording only has one.
85
+ export function echoes(content, texts) {
86
+ const said = interestTerms(texts);
87
+ if (!said.size) return false;
88
+ const need = interestTerms([content]).size < 2 ? 1 : 2;
89
+ return touches(content, said, need);
90
+ }
91
+
92
+ // A restatement may add words, as in "搬到上海" remembered as "住在上海".
93
+ // The last distinctive word of what is written still has to be one that was
94
+ // said. Swapping that word ("辞职" written as "结婚") does not count.
95
+ export function grounded(content, texts) {
96
+ const said = interestTerms(texts);
97
+ const terms = [...interestTerms([content])];
98
+ if (!terms.length || !said.size) return false;
99
+ return said.has(terms.at(-1));
100
+ }
101
+
102
+ // One set, or one set per speaker. An empty list means nothing was said.
103
+ export function cueList(cue, cues) {
104
+ if (Array.isArray(cues) && cues.length)
105
+ return cues.filter((set) => set?.size);
106
+ if (cue?.size) return [cue];
107
+ return [];
108
+ }
109
+
110
+ export function anyTouches(content, cues, need = 2) {
111
+ return cueList(null, cues).some((cue) => touches(content, cue, need));
112
+ }
113
+
114
+ // Two wordings of the same self-thread. A longer sentence that still
115
+ // carries the shorter wish's distinctive pairs is the same thread.
116
+ // Sharing only a frame ("我想把…完") is not enough.
117
+ export function sameSelf(a, b) {
118
+ if (similar(a, b, 0.75)) return true;
119
+ const left = interestTerms([a]);
120
+ const right = interestTerms([b]);
121
+ if (!left.size || !right.size) return false;
122
+ let shared = 0;
123
+ for (const term of left) if (right.has(term)) shared++;
124
+ const shorter = Math.min(left.size, right.size);
125
+ const longer = Math.max(left.size, right.size);
126
+ return shared >= 2 && shared / shorter >= 0.6 && shared / longer >= 0.22;
127
+ }
128
+
129
+ // Whether someone's own words met this wish. Two distinctive pairs, or
130
+ // one when the wish only has one; naming a title or work in it is enough.
131
+ // A single Chinese pair is still not a meeting.
132
+ export function meetsLife(content, cue) {
133
+ const wish = interestTerms([content]);
134
+ if (!wish.size || !cue?.size) return false;
135
+ if (touches(content, cue, wish.size < 2 ? 1 : 2)) return true;
136
+ return namesProject(wish, cue);
137
+ }
138
+
139
+ // A later note that puts this wish down. The same sentence must name
140
+ // the wish, not just share a leftover pair like "子里"; "封面" or
141
+ // walking up to the button is not putting it down.
142
+ const LIFE_FRAME = new Set(
143
+ "游戏 决定 完全 不看 评分 讨论 一下 开始 起来 出来 一点 开新 新游 看看 试试 打算 想要".split(
144
+ " ",
145
+ ),
146
+ );
147
+
148
+ export function leftLife(wish, thought) {
149
+ const want = String(wish || "");
150
+ const note = String(thought || "");
151
+ if (!want || !note) return false;
152
+ const marks = [...interestTerms([want])].filter(
153
+ (term) =>
154
+ !LIFE_FRAME.has(term) &&
155
+ (/^[a-z0-9]{3,}$/.test(term) ||
156
+ (/[\u4e00-\u9fff]{2}/.test(term) &&
157
+ !/[里的了着吗呢去上来]$/.test(term))),
158
+ );
159
+ if (!marks.length) return false;
160
+ return note.split(/(?<=[。!?\n])/).some((sentence) => {
161
+ if (
162
+ !/(?:封了|放下了|到此为止|不想再(?:过|想|开|玩|打|写)|不再过|不继续|先放下)/.test(
163
+ sentence,
164
+ )
165
+ )
166
+ return false;
167
+ const cue = interestTerms([sentence]);
168
+ return marks.some((term) => cue.has(term) || sentence.includes(term));
169
+ });
170
+ }
171
+
172
+ // A later note that is still this wish: the same wording, a title in it,
173
+ // two shared pairs, or one pair that is not just a frame like "游戏".
174
+ export function aboutLife(wish, thought) {
175
+ const want = String(wish || "");
176
+ const note = String(thought || "");
177
+ if (!want || !note) return false;
178
+ if (sameSelf(want, note)) return true;
179
+ const cue = interestTerms([note]);
180
+ if (meetsLife(want, cue)) return true;
181
+ const terms = interestTerms([want]);
182
+ let shared = 0;
183
+ for (const term of terms) if (cue.has(term)) shared++;
184
+ if (shared >= 2) return true;
185
+ for (const term of terms)
186
+ if (cue.has(term) && !LIFE_FRAME.has(term)) return true;
187
+ return false;
188
+ }
189
+
190
+ // A wish she is living for herself: something she wants to do or become.
191
+ // Advice, a promise about how she will treat someone, and watching over
192
+ // another person's state stay as threads; they do not take livingFor.
193
+
194
+ export function ownLife(content) {
195
+ const text = String(content || "");
196
+ if (/^(?:我)?(?:会|愿意|想)?(?:建议|劝|提醒|鼓励|答应)/.test(text))
197
+ return false;
198
+ return /(?:希望成为|想.{0,6}(?:看|学|玩|打|去|读|写|找|把|自己)|打算(?:开|玩|看|学|去)|决定(?:开|玩|看|学)|更想)/.test(
199
+ text,
200
+ );
201
+ }