luckytri 1.0.4 → 1.0.6

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 (156) hide show
  1. package/LICENSE +21 -21
  2. package/README.en.md +2 -0
  3. package/README.md +2 -0
  4. package/docs/en/CHANGELOG.md +20 -13
  5. package/docs/en/guide.md +7 -5
  6. package/docs/en/her-life.md +2 -2
  7. package/docs/en/webui.md +1 -1
  8. package/docs/zh/CHANGELOG.md +20 -13
  9. package/docs/zh/guide.md +7 -5
  10. package/docs/zh/her-life.md +2 -2
  11. package/docs/zh/webui.md +1 -1
  12. package/package.json +2 -1
  13. package/public/app/assets/ChatsPage-CFMVozoG.css +1 -0
  14. package/public/app/assets/{ChatsPage-CshdtTzV.js → ChatsPage-DCYMkJ91.js} +2 -2
  15. package/public/app/assets/{Empty-C7yzOBzy.js → Empty-CLyZkxR5.js} +1 -1
  16. package/public/app/assets/{Empty-DmUB2-Bk.css → Empty-DIobYG3x.css} +1 -1
  17. package/public/app/assets/{Field-BjFv4Rfn.js → Field-BpaRwLI_.js} +1 -1
  18. package/public/app/assets/{HeartPage-eqo6ru16.js → HeartPage-BIOMTiwr.js} +1 -1
  19. package/public/app/assets/HeartPage-C-2jvgzF.css +1 -0
  20. package/public/app/assets/{LifePage-CN8GE5NK.js → LifePage-BCgM4JkR.js} +1 -1
  21. package/public/app/assets/LifePage-CG1OHbRK.css +1 -0
  22. package/public/app/assets/MemoryPage-C_Bu4rfb.css +1 -0
  23. package/public/app/assets/{MemoryPage-CCpMN4Wg.js → MemoryPage-vShvRqMt.js} +1 -1
  24. package/public/app/assets/NaturePage-CPZlImT0.css +1 -0
  25. package/public/app/assets/{NaturePage-C0JqdBTR.js → NaturePage-Cy9ptr4G.js} +2 -2
  26. package/public/app/assets/PeoplePage-3RRUITDz.css +1 -0
  27. package/public/app/assets/{PeoplePage-BXGBbO4u.js → PeoplePage-CUZekB2E.js} +1 -1
  28. package/public/app/assets/{PluginsPage-Dksp5AV5.js → PluginsPage-1RM4rmJP.js} +1 -1
  29. package/public/app/assets/{SystemPage-BenIyTvk.css → SystemPage-BI2CB5Ig.css} +1 -1
  30. package/public/app/assets/{SystemPage-Cd7aa8eE.js → SystemPage-BeT5TmIV.js} +1 -1
  31. package/public/app/assets/TimePage-C-guwPk2.css +1 -0
  32. package/public/app/assets/{TimePage-Bs_zImb4.js → TimePage-taTmPMM8.js} +2 -2
  33. package/public/app/assets/{index-BHZcHUMh.css → index-DY5AM0Hz.css} +1 -1
  34. package/public/app/assets/{index-CyRtYxP3.js → index-DdYwC5ZU.js} +3 -3
  35. package/public/app/assets/{knowledge-BJOIyuJo.js → knowledge-DJmfu2KN.js} +1 -1
  36. package/public/app/assets/{media-Bwtx8blz.js → media-BEtnE0Gv.js} +1 -1
  37. package/public/app/assets/{mind-DtTVrW6Z.js → mind-Dtiw0-QK.js} +1 -1
  38. package/public/app/index.html +6 -5
  39. package/public/guide.en.html +11 -3
  40. package/public/guide.html +6 -3
  41. package/public/tutorial.en.md +2 -0
  42. package/public/tutorial.md +2 -0
  43. package/scripts/import-data.js +128 -128
  44. package/scripts/proxy-config.js +167 -167
  45. package/scripts/service-supervisor.js +50 -0
  46. package/scripts/start-server.js +71 -16
  47. package/scripts/update-instance.js +201 -201
  48. package/server/channels/adapters.js +27 -27
  49. package/server/channels/onebot/adapter.js +288 -288
  50. package/server/channels/qqbot/adapter.js +253 -253
  51. package/server/channels/qqbot/api.js +199 -199
  52. package/server/channels/qqbot/credentials.js +11 -11
  53. package/server/channels/qqbot/gateway.js +274 -274
  54. package/server/channels/qqbot/index.js +389 -389
  55. package/server/channels/segments.js +40 -40
  56. package/server/channels/session-key.js +153 -153
  57. package/server/channels/state.js +42 -42
  58. package/server/core/api.js +564 -564
  59. package/server/core/context-builder.js +288 -288
  60. package/server/core/context-compactor.js +454 -454
  61. package/server/core/conversation-cues.js +325 -325
  62. package/server/core/conversation-manager.js +87 -87
  63. package/server/core/feedback.js +8 -8
  64. package/server/core/group-style.js +72 -72
  65. package/server/core/initiative-context.js +66 -66
  66. package/server/core/input-budget.js +32 -32
  67. package/server/core/local-demo.js +98 -98
  68. package/server/core/message-manager.js +118 -118
  69. package/server/core/message-scheduler.js +78 -78
  70. package/server/core/model-json.js +190 -190
  71. package/server/core/model-presets.js +900 -900
  72. package/server/core/name-call.js +29 -29
  73. package/server/core/network.js +157 -157
  74. package/server/core/person-name.js +22 -22
  75. package/server/core/persona-manager.js +2 -1
  76. package/server/core/reply-delivery.js +404 -403
  77. package/server/core/reply-target-resolver.js +50 -50
  78. package/server/core/response-generator.js +50 -50
  79. package/server/core/response-validator.js +14 -2
  80. package/server/core/retired-prompts.js +51 -51
  81. package/server/core/sessions.js +109 -109
  82. package/server/core/speaker-names.js +92 -92
  83. package/server/core/topic-tracker.js +65 -65
  84. package/server/http.js +18 -18
  85. package/server/i18n/decisions.js +209 -206
  86. package/server/i18n/errors.js +4 -0
  87. package/server/i18n/index.js +144 -144
  88. package/server/i18n/models.js +111 -111
  89. package/server/knowledge/api.js +342 -342
  90. package/server/knowledge/embedding-profile.js +114 -114
  91. package/server/knowledge/index.js +13 -13
  92. package/server/knowledge/retrieval.js +93 -93
  93. package/server/knowledge/schema.js +158 -158
  94. package/server/knowledge/vector-index.js +90 -90
  95. package/server/mind/affect.js +265 -265
  96. package/server/mind/attention.js +200 -200
  97. package/server/mind/bonds.js +565 -565
  98. package/server/mind/clock.js +83 -83
  99. package/server/mind/continuity.js +562 -562
  100. package/server/mind/conversation-origin.js +175 -175
  101. package/server/mind/days.js +210 -210
  102. package/server/mind/evidence-read.js +45 -45
  103. package/server/mind/faces.js +373 -373
  104. package/server/mind/guard.js +60 -60
  105. package/server/mind/initiative.js +338 -338
  106. package/server/mind/life/activities.js +21 -21
  107. package/server/mind/life/context.js +330 -323
  108. package/server/mind/life/diary.js +20 -0
  109. package/server/mind/life/growth.js +261 -254
  110. package/server/mind/life/index.js +10 -2
  111. package/server/mind/life/presence.js +305 -305
  112. package/server/mind/meetings.js +1069 -1069
  113. package/server/mind/memory-policy.js +48 -48
  114. package/server/mind/memory.js +888 -888
  115. package/server/mind/nature.js +358 -358
  116. package/server/mind/novelty.js +19 -19
  117. package/server/mind/periods.js +118 -118
  118. package/server/mind/reading.js +120 -120
  119. package/server/mind/relationship-context.js +71 -0
  120. package/server/mind/relationships.js +390 -279
  121. package/server/mind/salience.js +201 -201
  122. package/server/mind/schema.js +567 -567
  123. package/server/mind/self.js +484 -484
  124. package/server/mind/thoughts.js +274 -274
  125. package/server/mind/time/agenda.js +242 -242
  126. package/server/mind/time/api.js +200 -200
  127. package/server/mind/time/attention.js +34 -34
  128. package/server/mind/time/delivery-links.js +130 -130
  129. package/server/mind/time/model-material.js +77 -77
  130. package/server/mind/time/presentation.js +51 -51
  131. package/server/mind/time/schedule.js +83 -83
  132. package/server/mind/time/schema.js +84 -84
  133. package/server/mind/time/search.js +383 -383
  134. package/server/mind/time/sharing.js +472 -472
  135. package/server/mind/time/task-links.js +311 -311
  136. package/server/mind/time/works.js +432 -432
  137. package/server/mind/traits.js +191 -191
  138. package/server/mind/view.js +9 -1
  139. package/server/runtime/installation.js +116 -116
  140. package/server/runtime/update-execution.js +2 -1
  141. package/server/runtime/update-manager.js +140 -140
  142. package/server/storage/data-package.js +298 -298
  143. package/server/storage/data-transfer-api.js +50 -50
  144. package/server/storage/data-transfer-worker.js +18 -18
  145. package/server/storage/data-transfer.js +416 -416
  146. package/server/studio/display-names.js +139 -139
  147. package/server/studio/management.js +102 -102
  148. package/server/studio/updates.js +144 -144
  149. package/server/version.js +10 -10
  150. package/public/app/assets/ChatsPage-DfyPCS9N.css +0 -1
  151. package/public/app/assets/HeartPage-Bft9wZp5.css +0 -1
  152. package/public/app/assets/LifePage-BUi5euBF.css +0 -1
  153. package/public/app/assets/MemoryPage-cZvXfkXb.css +0 -1
  154. package/public/app/assets/NaturePage-CHkpb5NK.css +0 -1
  155. package/public/app/assets/PeoplePage-BTU0H1pM.css +0 -1
  156. package/public/app/assets/TimePage-BOms_n4I.css +0 -1
@@ -1,83 +1,83 @@
1
- import { dayKey, zonedTime } from "../util.js";
2
- import { localClock } from "../../core/conversation-cues.js";
3
- import { gameText } from "./presentation.js";
4
- export function spokenDate(words, at, zone) {
5
- const absolute = String(words).match(/20\d{2}-\d{2}-\d{2}(?: \d{2}:\d{2})?/);
6
- if (absolute)
7
- return {
8
- dueAt: zonedTime(absolute[0], zone),
9
- duePrecision: absolute[0].includes(":") ? "time" : "day",
10
- };
11
- if (/后天|明天|明晚|今晚|今天/.test(words)) {
12
- const offset = /后天/.test(words) ? 2 : /明天|明晚/.test(words) ? 1 : 0;
13
- return {
14
- dueAt: zonedTime(dayKey(at + offset * 86400000, zone) + " 23:59", zone),
15
- duePrecision: "day",
16
- };
17
- }
18
- return { dueAt: null, duePrecision: "none" };
19
- }
20
- export function nextAwakeSlot(mind, now) {
21
- const zone = mind.timeZone(),
22
- rhythm = mind.nature.current(now).rhythm;
23
- let at = Math.ceil(now / 300000) * 300000;
24
- if (rhythm?.enabled) {
25
- const clock = localClock(now, zone),
26
- wake = zonedTime(dayKey(now, zone) + " " + rhythm.wake, zone);
27
- if (wake > now) at = wake;
28
- else if (
29
- mind.affect.state(now).phase === "asleep" ||
30
- mind.affect.state(now).phase === "sleepy"
31
- )
32
- at = zonedTime(dayKey(now + 86400000, zone) + " " + rhythm.wake, zone);
33
- }
34
- return at;
35
- }
36
- export function deadlineAt(at, precision, zone) {
37
- if (!Number.isFinite(at)) return null;
38
- return precision === "day"
39
- ? zonedTime(dayKey(at, zone) + " 23:59", zone) + 59999
40
- : at;
41
- }
42
- export function taskSchedule(task, time, now = time.now()) {
43
- const plan = task.checkpoint?.schedule;
44
- const waiting = task.state === "waiting";
45
- const focus =
46
- plan?.durationMinutes || plan?.focusMinutes || time.settings().focusMinutes;
47
- const proposed =
48
- plan?.chosenAt || plan?.proposedAt > now
49
- ? plan.proposedAt
50
- : task.state === "scheduled" && task.ready_at > now
51
- ? task.ready_at
52
- : null;
53
- const live =
54
- task.state === "doing"
55
- ? time.db
56
- .prepare(
57
- "SELECT started FROM mind_time_spans WHERE task_id=? AND ended IS NULL",
58
- )
59
- .get(task.id)
60
- : null;
61
- return {
62
- earliestAt: task.ready_at,
63
- proposedAt: proposed,
64
- proposedEnd: proposed ? proposed + focus * 60000 : null,
65
- startedAt: live?.started || null,
66
- focusMinutes: focus,
67
- chosenAt: plan?.chosenAt || null,
68
- chosenBy: plan?.chosenBy || null,
69
- durationMinutes: plan?.durationMinutes || null,
70
- reason: plan?.reason || "",
71
- conditional: waiting,
72
- deadlinePrecision: task.due_precision || "time",
73
- deadlineAt: task.due_at,
74
- nextAttemptAt:
75
- task.next_step > now && task.next_step < 8e15 ? task.next_step : null,
76
- outcome:
77
- task.activity === "game"
78
- ? gameText(plan?.outcome || task.checkpoint?.contract?.outcome || "")
79
- : plan?.outcome || task.checkpoint?.contract?.outcome || "",
80
- estimatedMs: task.checkpoint?.activityClock?.plannedMs || null,
81
- condition: waiting ? task.wait_reason : "",
82
- };
83
- }
1
+ import { dayKey, zonedTime } from "../util.js";
2
+ import { localClock } from "../../core/conversation-cues.js";
3
+ import { gameText } from "./presentation.js";
4
+ export function spokenDate(words, at, zone) {
5
+ const absolute = String(words).match(/20\d{2}-\d{2}-\d{2}(?: \d{2}:\d{2})?/);
6
+ if (absolute)
7
+ return {
8
+ dueAt: zonedTime(absolute[0], zone),
9
+ duePrecision: absolute[0].includes(":") ? "time" : "day",
10
+ };
11
+ if (/后天|明天|明晚|今晚|今天/.test(words)) {
12
+ const offset = /后天/.test(words) ? 2 : /明天|明晚/.test(words) ? 1 : 0;
13
+ return {
14
+ dueAt: zonedTime(dayKey(at + offset * 86400000, zone) + " 23:59", zone),
15
+ duePrecision: "day",
16
+ };
17
+ }
18
+ return { dueAt: null, duePrecision: "none" };
19
+ }
20
+ export function nextAwakeSlot(mind, now) {
21
+ const zone = mind.timeZone(),
22
+ rhythm = mind.nature.current(now).rhythm;
23
+ let at = Math.ceil(now / 300000) * 300000;
24
+ if (rhythm?.enabled) {
25
+ const clock = localClock(now, zone),
26
+ wake = zonedTime(dayKey(now, zone) + " " + rhythm.wake, zone);
27
+ if (wake > now) at = wake;
28
+ else if (
29
+ mind.affect.state(now).phase === "asleep" ||
30
+ mind.affect.state(now).phase === "sleepy"
31
+ )
32
+ at = zonedTime(dayKey(now + 86400000, zone) + " " + rhythm.wake, zone);
33
+ }
34
+ return at;
35
+ }
36
+ export function deadlineAt(at, precision, zone) {
37
+ if (!Number.isFinite(at)) return null;
38
+ return precision === "day"
39
+ ? zonedTime(dayKey(at, zone) + " 23:59", zone) + 59999
40
+ : at;
41
+ }
42
+ export function taskSchedule(task, time, now = time.now()) {
43
+ const plan = task.checkpoint?.schedule;
44
+ const waiting = task.state === "waiting";
45
+ const focus =
46
+ plan?.durationMinutes || plan?.focusMinutes || time.settings().focusMinutes;
47
+ const proposed =
48
+ plan?.chosenAt || plan?.proposedAt > now
49
+ ? plan.proposedAt
50
+ : task.state === "scheduled" && task.ready_at > now
51
+ ? task.ready_at
52
+ : null;
53
+ const live =
54
+ task.state === "doing"
55
+ ? time.db
56
+ .prepare(
57
+ "SELECT started FROM mind_time_spans WHERE task_id=? AND ended IS NULL",
58
+ )
59
+ .get(task.id)
60
+ : null;
61
+ return {
62
+ earliestAt: task.ready_at,
63
+ proposedAt: proposed,
64
+ proposedEnd: proposed ? proposed + focus * 60000 : null,
65
+ startedAt: live?.started || null,
66
+ focusMinutes: focus,
67
+ chosenAt: plan?.chosenAt || null,
68
+ chosenBy: plan?.chosenBy || null,
69
+ durationMinutes: plan?.durationMinutes || null,
70
+ reason: plan?.reason || "",
71
+ conditional: waiting,
72
+ deadlinePrecision: task.due_precision || "time",
73
+ deadlineAt: task.due_at,
74
+ nextAttemptAt:
75
+ task.next_step > now && task.next_step < 8e15 ? task.next_step : null,
76
+ outcome:
77
+ task.activity === "game"
78
+ ? gameText(plan?.outcome || task.checkpoint?.contract?.outcome || "")
79
+ : plan?.outcome || task.checkpoint?.contract?.outcome || "",
80
+ estimatedMs: task.checkpoint?.activityClock?.plannedMs || null,
81
+ condition: waiting ? task.wait_reason : "",
82
+ };
83
+ }
@@ -1,84 +1,84 @@
1
- export function migrateTime(db) {
2
- db.exec(`
3
- CREATE TABLE IF NOT EXISTS mind_time_projects(id TEXT PRIMARY KEY,created INTEGER NOT NULL,updated INTEGER NOT NULL,kind TEXT NOT NULL,title TEXT NOT NULL,why TEXT NOT NULL DEFAULT '',state TEXT NOT NULL DEFAULT 'active',session_id TEXT,discretion TEXT NOT NULL DEFAULT 'open',sources TEXT NOT NULL DEFAULT '[]',bible TEXT NOT NULL DEFAULT '{}',summary TEXT NOT NULL DEFAULT '',serial INTEGER NOT NULL DEFAULT 0,revision INTEGER NOT NULL DEFAULT 1);
4
- CREATE TABLE IF NOT EXISTS mind_time_tasks(id TEXT PRIMARY KEY,created INTEGER NOT NULL,updated INTEGER NOT NULL,kind TEXT NOT NULL,activity TEXT NOT NULL,title TEXT NOT NULL,why TEXT NOT NULL DEFAULT '',state TEXT NOT NULL DEFAULT 'todo',ready_at INTEGER NOT NULL,due_at INTEGER,session_id TEXT,subject TEXT,discretion TEXT NOT NULL DEFAULT 'open',sources TEXT NOT NULL DEFAULT '[]',anticipation_id TEXT UNIQUE,project_id TEXT,work_id TEXT,checkpoint TEXT NOT NULL DEFAULT '{}',revision INTEGER NOT NULL DEFAULT 1,next_step INTEGER NOT NULL DEFAULT 0,wait_reason TEXT NOT NULL DEFAULT '',share_state TEXT NOT NULL DEFAULT 'none',share_reason TEXT NOT NULL DEFAULT '',depends_on TEXT,lease TEXT,lease_at INTEGER,completed INTEGER);
5
- CREATE INDEX IF NOT EXISTS mind_time_tasks_queue ON mind_time_tasks(state,ready_at,next_step);
6
- CREATE UNIQUE INDEX IF NOT EXISTS mind_time_single_main ON mind_time_tasks((1)) WHERE state='doing';
7
- CREATE TABLE IF NOT EXISTS mind_time_spans(id TEXT PRIMARY KEY,task_id TEXT NOT NULL,started INTEGER NOT NULL,updated INTEGER NOT NULL,ended INTEGER,active_ms INTEGER NOT NULL DEFAULT 0);
8
- CREATE INDEX IF NOT EXISTS mind_time_spans_task ON mind_time_spans(task_id,started);
9
- CREATE TABLE IF NOT EXISTS mind_time_events(id INTEGER PRIMARY KEY,created INTEGER NOT NULL,task_id TEXT,kind TEXT NOT NULL,reason TEXT NOT NULL DEFAULT '',data TEXT NOT NULL DEFAULT '{}');
10
- CREATE INDEX IF NOT EXISTS mind_time_events_time ON mind_time_events(created);
11
- CREATE TABLE IF NOT EXISTS mind_time_works(id TEXT PRIMARY KEY,created INTEGER NOT NULL,updated INTEGER NOT NULL,task_id TEXT,project_id TEXT,ordinal INTEGER NOT NULL DEFAULT 1,title TEXT NOT NULL,state TEXT NOT NULL DEFAULT 'draft',version INTEGER NOT NULL DEFAULT 0,session_id TEXT,discretion TEXT NOT NULL DEFAULT 'open',legacy_creation TEXT UNIQUE,UNIQUE(project_id,ordinal));
12
- CREATE TABLE IF NOT EXISTS mind_time_versions(id TEXT PRIMARY KEY,work_id TEXT NOT NULL,version INTEGER NOT NULL,created INTEGER NOT NULL,title TEXT NOT NULL,content TEXT NOT NULL,summary TEXT NOT NULL DEFAULT '',sources TEXT NOT NULL DEFAULT '[]',run_id TEXT,UNIQUE(work_id,version));
13
- CREATE INDEX IF NOT EXISTS mind_time_versions_work ON mind_time_versions(work_id,version);
14
- CREATE INDEX IF NOT EXISTS mind_time_works_recent ON mind_time_works(updated DESC);
15
- CREATE INDEX IF NOT EXISTS mind_time_works_task ON mind_time_works(task_id);
16
- CREATE INDEX IF NOT EXISTS mind_time_projects_recent ON mind_time_projects(updated DESC);
17
- CREATE TABLE IF NOT EXISTS mind_time_sources(id TEXT PRIMARY KEY,project_id TEXT NOT NULL,created INTEGER NOT NULL,title TEXT NOT NULL,url TEXT NOT NULL,content TEXT NOT NULL,hash TEXT NOT NULL,UNIQUE(project_id,url,hash));
18
- CREATE TABLE IF NOT EXISTS mind_time_searches(id INTEGER PRIMARY KEY,created INTEGER NOT NULL,provider TEXT NOT NULL,query TEXT NOT NULL,state TEXT NOT NULL,error TEXT NOT NULL DEFAULT '');
19
- CREATE TABLE IF NOT EXISTS mind_time_shares(id TEXT PRIMARY KEY,created INTEGER NOT NULL,updated INTEGER NOT NULL,work_id TEXT NOT NULL,version INTEGER NOT NULL,session_id TEXT NOT NULL,offset INTEGER NOT NULL DEFAULT 0,state TEXT NOT NULL DEFAULT 'pending',reason TEXT NOT NULL DEFAULT '',trace_id TEXT,UNIQUE(work_id,version,session_id));
20
- CREATE TABLE IF NOT EXISTS mind_time_task_aliases(kind TEXT NOT NULL,alias_id TEXT NOT NULL,task_id TEXT NOT NULL,created INTEGER NOT NULL,PRIMARY KEY(kind,alias_id));
21
- CREATE INDEX IF NOT EXISTS mind_time_task_aliases_task ON mind_time_task_aliases(task_id);
22
- CREATE TABLE IF NOT EXISTS mind_time_activity_ticks(span_id TEXT NOT NULL,started INTEGER NOT NULL,ended INTEGER NOT NULL,PRIMARY KEY(span_id,ended));
23
- CREATE INDEX IF NOT EXISTS mind_time_activity_ticks_time ON mind_time_activity_ticks(ended,started);
24
- CREATE TABLE IF NOT EXISTS mind_time_commitment_reviews(seq INTEGER PRIMARY KEY,reviewed INTEGER NOT NULL,task_ids TEXT NOT NULL DEFAULT '[]');
25
- CREATE INDEX IF NOT EXISTS mind_time_assistant_review ON core_events(seq,time,session_id) WHERE role='assistant';
26
- CREATE INDEX IF NOT EXISTS mind_time_source_lookup ON mind_time_task_aliases(kind,substr(alias_id,instr(alias_id,':')+1));
27
- `);
28
- const columns = new Set(
29
- db
30
- .prepare("PRAGMA table_info(mind_time_tasks)")
31
- .all()
32
- .map((c) => c.name),
33
- );
34
- if (!columns.has("intent_key"))
35
- db.exec("ALTER TABLE mind_time_tasks ADD COLUMN intent_key TEXT");
36
- if (!columns.has("due_precision"))
37
- db.exec(
38
- "ALTER TABLE mind_time_tasks ADD COLUMN due_precision TEXT NOT NULL DEFAULT 'time'",
39
- );
40
- if (!columns.has("priority"))
41
- db.exec(
42
- "ALTER TABLE mind_time_tasks ADD COLUMN priority INTEGER NOT NULL DEFAULT 1 CHECK(priority BETWEEN 0 AND 3); UPDATE mind_time_tasks SET priority=2 WHERE kind='promise';",
43
- );
44
- db.exec(
45
- "CREATE INDEX IF NOT EXISTS mind_time_tasks_intent ON mind_time_tasks(intent_key);",
46
- );
47
- const sourceColumns = new Set(
48
- db
49
- .prepare("PRAGMA table_info(mind_time_sources)")
50
- .all()
51
- .map((c) => c.name),
52
- );
53
- for (const [name, fallback] of [
54
- ["kind", "web"],
55
- ["model", ""],
56
- ["uncertainty", ""],
57
- ])
58
- if (!sourceColumns.has(name))
59
- db.exec(
60
- `ALTER TABLE mind_time_sources ADD COLUMN ${name} TEXT NOT NULL DEFAULT '${fallback}'`,
61
- );
62
- for (const [table, column, type, fallback] of [
63
- ["mind_time_sources", "timing", "TEXT", "'{}'"],
64
- ["mind_time_versions", "provenance", "TEXT", "'{}'"],
65
- ["mind_time_spans", "engaged_ms", "INTEGER", "0"],
66
- ["mind_time_spans", "clocked", "INTEGER", "0"],
67
- ["mind_time_shares", "review_offset", "INTEGER", "0"],
68
- ["mind_time_shares", "review_notes", "TEXT", "'[]'"],
69
- ["mind_time_shares", "report", "TEXT", "'[]'"],
70
- ["mind_time_shares", "send_index", "INTEGER", "0"],
71
- ["mind_time_shares", "delivery_kind", "TEXT", "'body'"],
72
- ["mind_time_shares", "next_step", "INTEGER", "0"],
73
- ["mind_time_searches", "purpose", "TEXT", "'activity'"],
74
- ])
75
- if (
76
- !db
77
- .prepare(`PRAGMA table_info(${table})`)
78
- .all()
79
- .some((c) => c.name === column)
80
- )
81
- db.exec(
82
- `ALTER TABLE ${table} ADD COLUMN ${column} ${type} NOT NULL DEFAULT ${fallback}`,
83
- );
84
- }
1
+ export function migrateTime(db) {
2
+ db.exec(`
3
+ CREATE TABLE IF NOT EXISTS mind_time_projects(id TEXT PRIMARY KEY,created INTEGER NOT NULL,updated INTEGER NOT NULL,kind TEXT NOT NULL,title TEXT NOT NULL,why TEXT NOT NULL DEFAULT '',state TEXT NOT NULL DEFAULT 'active',session_id TEXT,discretion TEXT NOT NULL DEFAULT 'open',sources TEXT NOT NULL DEFAULT '[]',bible TEXT NOT NULL DEFAULT '{}',summary TEXT NOT NULL DEFAULT '',serial INTEGER NOT NULL DEFAULT 0,revision INTEGER NOT NULL DEFAULT 1);
4
+ CREATE TABLE IF NOT EXISTS mind_time_tasks(id TEXT PRIMARY KEY,created INTEGER NOT NULL,updated INTEGER NOT NULL,kind TEXT NOT NULL,activity TEXT NOT NULL,title TEXT NOT NULL,why TEXT NOT NULL DEFAULT '',state TEXT NOT NULL DEFAULT 'todo',ready_at INTEGER NOT NULL,due_at INTEGER,session_id TEXT,subject TEXT,discretion TEXT NOT NULL DEFAULT 'open',sources TEXT NOT NULL DEFAULT '[]',anticipation_id TEXT UNIQUE,project_id TEXT,work_id TEXT,checkpoint TEXT NOT NULL DEFAULT '{}',revision INTEGER NOT NULL DEFAULT 1,next_step INTEGER NOT NULL DEFAULT 0,wait_reason TEXT NOT NULL DEFAULT '',share_state TEXT NOT NULL DEFAULT 'none',share_reason TEXT NOT NULL DEFAULT '',depends_on TEXT,lease TEXT,lease_at INTEGER,completed INTEGER);
5
+ CREATE INDEX IF NOT EXISTS mind_time_tasks_queue ON mind_time_tasks(state,ready_at,next_step);
6
+ CREATE UNIQUE INDEX IF NOT EXISTS mind_time_single_main ON mind_time_tasks((1)) WHERE state='doing';
7
+ CREATE TABLE IF NOT EXISTS mind_time_spans(id TEXT PRIMARY KEY,task_id TEXT NOT NULL,started INTEGER NOT NULL,updated INTEGER NOT NULL,ended INTEGER,active_ms INTEGER NOT NULL DEFAULT 0);
8
+ CREATE INDEX IF NOT EXISTS mind_time_spans_task ON mind_time_spans(task_id,started);
9
+ CREATE TABLE IF NOT EXISTS mind_time_events(id INTEGER PRIMARY KEY,created INTEGER NOT NULL,task_id TEXT,kind TEXT NOT NULL,reason TEXT NOT NULL DEFAULT '',data TEXT NOT NULL DEFAULT '{}');
10
+ CREATE INDEX IF NOT EXISTS mind_time_events_time ON mind_time_events(created);
11
+ CREATE TABLE IF NOT EXISTS mind_time_works(id TEXT PRIMARY KEY,created INTEGER NOT NULL,updated INTEGER NOT NULL,task_id TEXT,project_id TEXT,ordinal INTEGER NOT NULL DEFAULT 1,title TEXT NOT NULL,state TEXT NOT NULL DEFAULT 'draft',version INTEGER NOT NULL DEFAULT 0,session_id TEXT,discretion TEXT NOT NULL DEFAULT 'open',legacy_creation TEXT UNIQUE,UNIQUE(project_id,ordinal));
12
+ CREATE TABLE IF NOT EXISTS mind_time_versions(id TEXT PRIMARY KEY,work_id TEXT NOT NULL,version INTEGER NOT NULL,created INTEGER NOT NULL,title TEXT NOT NULL,content TEXT NOT NULL,summary TEXT NOT NULL DEFAULT '',sources TEXT NOT NULL DEFAULT '[]',run_id TEXT,UNIQUE(work_id,version));
13
+ CREATE INDEX IF NOT EXISTS mind_time_versions_work ON mind_time_versions(work_id,version);
14
+ CREATE INDEX IF NOT EXISTS mind_time_works_recent ON mind_time_works(updated DESC);
15
+ CREATE INDEX IF NOT EXISTS mind_time_works_task ON mind_time_works(task_id);
16
+ CREATE INDEX IF NOT EXISTS mind_time_projects_recent ON mind_time_projects(updated DESC);
17
+ CREATE TABLE IF NOT EXISTS mind_time_sources(id TEXT PRIMARY KEY,project_id TEXT NOT NULL,created INTEGER NOT NULL,title TEXT NOT NULL,url TEXT NOT NULL,content TEXT NOT NULL,hash TEXT NOT NULL,UNIQUE(project_id,url,hash));
18
+ CREATE TABLE IF NOT EXISTS mind_time_searches(id INTEGER PRIMARY KEY,created INTEGER NOT NULL,provider TEXT NOT NULL,query TEXT NOT NULL,state TEXT NOT NULL,error TEXT NOT NULL DEFAULT '');
19
+ CREATE TABLE IF NOT EXISTS mind_time_shares(id TEXT PRIMARY KEY,created INTEGER NOT NULL,updated INTEGER NOT NULL,work_id TEXT NOT NULL,version INTEGER NOT NULL,session_id TEXT NOT NULL,offset INTEGER NOT NULL DEFAULT 0,state TEXT NOT NULL DEFAULT 'pending',reason TEXT NOT NULL DEFAULT '',trace_id TEXT,UNIQUE(work_id,version,session_id));
20
+ CREATE TABLE IF NOT EXISTS mind_time_task_aliases(kind TEXT NOT NULL,alias_id TEXT NOT NULL,task_id TEXT NOT NULL,created INTEGER NOT NULL,PRIMARY KEY(kind,alias_id));
21
+ CREATE INDEX IF NOT EXISTS mind_time_task_aliases_task ON mind_time_task_aliases(task_id);
22
+ CREATE TABLE IF NOT EXISTS mind_time_activity_ticks(span_id TEXT NOT NULL,started INTEGER NOT NULL,ended INTEGER NOT NULL,PRIMARY KEY(span_id,ended));
23
+ CREATE INDEX IF NOT EXISTS mind_time_activity_ticks_time ON mind_time_activity_ticks(ended,started);
24
+ CREATE TABLE IF NOT EXISTS mind_time_commitment_reviews(seq INTEGER PRIMARY KEY,reviewed INTEGER NOT NULL,task_ids TEXT NOT NULL DEFAULT '[]');
25
+ CREATE INDEX IF NOT EXISTS mind_time_assistant_review ON core_events(seq,time,session_id) WHERE role='assistant';
26
+ CREATE INDEX IF NOT EXISTS mind_time_source_lookup ON mind_time_task_aliases(kind,substr(alias_id,instr(alias_id,':')+1));
27
+ `);
28
+ const columns = new Set(
29
+ db
30
+ .prepare("PRAGMA table_info(mind_time_tasks)")
31
+ .all()
32
+ .map((c) => c.name),
33
+ );
34
+ if (!columns.has("intent_key"))
35
+ db.exec("ALTER TABLE mind_time_tasks ADD COLUMN intent_key TEXT");
36
+ if (!columns.has("due_precision"))
37
+ db.exec(
38
+ "ALTER TABLE mind_time_tasks ADD COLUMN due_precision TEXT NOT NULL DEFAULT 'time'",
39
+ );
40
+ if (!columns.has("priority"))
41
+ db.exec(
42
+ "ALTER TABLE mind_time_tasks ADD COLUMN priority INTEGER NOT NULL DEFAULT 1 CHECK(priority BETWEEN 0 AND 3); UPDATE mind_time_tasks SET priority=2 WHERE kind='promise';",
43
+ );
44
+ db.exec(
45
+ "CREATE INDEX IF NOT EXISTS mind_time_tasks_intent ON mind_time_tasks(intent_key);",
46
+ );
47
+ const sourceColumns = new Set(
48
+ db
49
+ .prepare("PRAGMA table_info(mind_time_sources)")
50
+ .all()
51
+ .map((c) => c.name),
52
+ );
53
+ for (const [name, fallback] of [
54
+ ["kind", "web"],
55
+ ["model", ""],
56
+ ["uncertainty", ""],
57
+ ])
58
+ if (!sourceColumns.has(name))
59
+ db.exec(
60
+ `ALTER TABLE mind_time_sources ADD COLUMN ${name} TEXT NOT NULL DEFAULT '${fallback}'`,
61
+ );
62
+ for (const [table, column, type, fallback] of [
63
+ ["mind_time_sources", "timing", "TEXT", "'{}'"],
64
+ ["mind_time_versions", "provenance", "TEXT", "'{}'"],
65
+ ["mind_time_spans", "engaged_ms", "INTEGER", "0"],
66
+ ["mind_time_spans", "clocked", "INTEGER", "0"],
67
+ ["mind_time_shares", "review_offset", "INTEGER", "0"],
68
+ ["mind_time_shares", "review_notes", "TEXT", "'[]'"],
69
+ ["mind_time_shares", "report", "TEXT", "'[]'"],
70
+ ["mind_time_shares", "send_index", "INTEGER", "0"],
71
+ ["mind_time_shares", "delivery_kind", "TEXT", "'body'"],
72
+ ["mind_time_shares", "next_step", "INTEGER", "0"],
73
+ ["mind_time_searches", "purpose", "TEXT", "'activity'"],
74
+ ])
75
+ if (
76
+ !db
77
+ .prepare(`PRAGMA table_info(${table})`)
78
+ .all()
79
+ .some((c) => c.name === column)
80
+ )
81
+ db.exec(
82
+ `ALTER TABLE ${table} ADD COLUMN ${column} ${type} NOT NULL DEFAULT ${fallback}`,
83
+ );
84
+ }