lifeos 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 (216) hide show
  1. package/LICENSE +21 -0
  2. package/README.en.md +202 -0
  3. package/README.md +202 -0
  4. package/assets/lifeos-rules.en.md +162 -0
  5. package/assets/lifeos-rules.zh.md +162 -0
  6. package/assets/lifeos.yaml +56 -0
  7. package/assets/prompts/AI_LLMResearch_Prompt.en.md +120 -0
  8. package/assets/prompts/AI_LLMResearch_Prompt.zh.md +120 -0
  9. package/assets/prompts/Art_ChinesePainting_Prompt.en.md +147 -0
  10. package/assets/prompts/Art_ChinesePainting_Prompt.zh.md +148 -0
  11. package/assets/prompts/Cryptography_Prompt.en.md +148 -0
  12. package/assets/prompts/Cryptography_Prompt.zh.md +147 -0
  13. package/assets/prompts/History_ChineseCulture_Prompt.en.md +98 -0
  14. package/assets/prompts/History_ChineseCulture_Prompt.zh.md +98 -0
  15. package/assets/prompts/Math_HigherMathematics_Prompt.en.md +117 -0
  16. package/assets/prompts/Math_HigherMathematics_Prompt.zh.md +116 -0
  17. package/assets/schema/Frontmatter_Schema.md +139 -0
  18. package/assets/skills/_shared/completion-report.en.md +30 -0
  19. package/assets/skills/_shared/completion-report.zh.md +30 -0
  20. package/assets/skills/_shared/dual-agent-orchestrator.en.md +40 -0
  21. package/assets/skills/_shared/dual-agent-orchestrator.zh.md +40 -0
  22. package/assets/skills/_shared/learning-lifecycle.en.md +53 -0
  23. package/assets/skills/_shared/learning-lifecycle.zh.md +53 -0
  24. package/assets/skills/_shared/lifecycle.en.md +84 -0
  25. package/assets/skills/_shared/lifecycle.zh.md +84 -0
  26. package/assets/skills/_shared/memory-protocol.en.md +36 -0
  27. package/assets/skills/_shared/memory-protocol.zh.md +36 -0
  28. package/assets/skills/_shared/template-loading.en.md +26 -0
  29. package/assets/skills/_shared/template-loading.zh.md +26 -0
  30. package/assets/skills/archive/SKILL.en.md +300 -0
  31. package/assets/skills/archive/SKILL.zh.md +300 -0
  32. package/assets/skills/ask/SKILL.en.md +164 -0
  33. package/assets/skills/ask/SKILL.zh.md +164 -0
  34. package/assets/skills/brainstorm/SKILL.en.md +242 -0
  35. package/assets/skills/brainstorm/SKILL.zh.md +242 -0
  36. package/assets/skills/brainstorm/references/action-options.en.md +65 -0
  37. package/assets/skills/brainstorm/references/action-options.zh.md +65 -0
  38. package/assets/skills/knowledge/SKILL.en.md +202 -0
  39. package/assets/skills/knowledge/SKILL.zh.md +202 -0
  40. package/assets/skills/project/SKILL.en.md +133 -0
  41. package/assets/skills/project/SKILL.zh.md +133 -0
  42. package/assets/skills/project/references/execution-agent-prompt.en.md +148 -0
  43. package/assets/skills/project/references/execution-agent-prompt.zh.md +148 -0
  44. package/assets/skills/project/references/planning-agent-prompt.en.md +162 -0
  45. package/assets/skills/project/references/planning-agent-prompt.zh.md +162 -0
  46. package/assets/skills/read-pdf/SKILL.en.md +199 -0
  47. package/assets/skills/read-pdf/SKILL.zh.md +199 -0
  48. package/assets/skills/read-pdf/scripts/read_pdf.py +354 -0
  49. package/assets/skills/research/SKILL.en.md +107 -0
  50. package/assets/skills/research/SKILL.zh.md +107 -0
  51. package/assets/skills/research/references/execution-agent-prompt.en.md +166 -0
  52. package/assets/skills/research/references/execution-agent-prompt.zh.md +166 -0
  53. package/assets/skills/research/references/planning-agent-prompt.en.md +129 -0
  54. package/assets/skills/research/references/planning-agent-prompt.zh.md +129 -0
  55. package/assets/skills/revise/SKILL.en.md +258 -0
  56. package/assets/skills/revise/SKILL.zh.md +258 -0
  57. package/assets/skills/revise/references/grading-protocol.en.md +99 -0
  58. package/assets/skills/revise/references/grading-protocol.zh.md +99 -0
  59. package/assets/skills/today/SKILL.en.md +211 -0
  60. package/assets/skills/today/SKILL.zh.md +211 -0
  61. package/assets/templates/en/Daily_Template.md +25 -0
  62. package/assets/templates/en/Draft_Template.md +29 -0
  63. package/assets/templates/en/Knowledge_Template.md +86 -0
  64. package/assets/templates/en/Project_Template.md +110 -0
  65. package/assets/templates/en/Research_Template.md +46 -0
  66. package/assets/templates/en/Retrospective_Template.md +89 -0
  67. package/assets/templates/en/Revise_Template.md +24 -0
  68. package/assets/templates/en/Wiki_Template.md +35 -0
  69. package/assets/templates/zh/Daily_Template.md +26 -0
  70. package/assets/templates/zh/Draft_Template.md +29 -0
  71. package/assets/templates/zh/Knowledge_Template.md +86 -0
  72. package/assets/templates/zh/Project_Template.md +110 -0
  73. package/assets/templates/zh/Research_Template.md +46 -0
  74. package/assets/templates/zh/Retrospective_Template.md +89 -0
  75. package/assets/templates/zh/Revise_Template.md +24 -0
  76. package/assets/templates/zh/Wiki_Template.md +35 -0
  77. package/bin/lifeos.js +24 -0
  78. package/dist/active-docs/citations.d.ts +20 -0
  79. package/dist/active-docs/citations.js +74 -0
  80. package/dist/active-docs/citations.js.map +1 -0
  81. package/dist/active-docs/derived-memory.d.ts +57 -0
  82. package/dist/active-docs/derived-memory.js +161 -0
  83. package/dist/active-docs/derived-memory.js.map +1 -0
  84. package/dist/active-docs/index.d.ts +51 -0
  85. package/dist/active-docs/index.js +165 -0
  86. package/dist/active-docs/index.js.map +1 -0
  87. package/dist/active-docs/long-term-profile.d.ts +24 -0
  88. package/dist/active-docs/long-term-profile.js +75 -0
  89. package/dist/active-docs/long-term-profile.js.map +1 -0
  90. package/dist/active-docs/taskboard.d.ts +12 -0
  91. package/dist/active-docs/taskboard.js +146 -0
  92. package/dist/active-docs/taskboard.js.map +1 -0
  93. package/dist/active-docs/userprofile.d.ts +12 -0
  94. package/dist/active-docs/userprofile.js +169 -0
  95. package/dist/active-docs/userprofile.js.map +1 -0
  96. package/dist/cli/commands/doctor.d.ts +9 -0
  97. package/dist/cli/commands/doctor.js +125 -0
  98. package/dist/cli/commands/doctor.js.map +1 -0
  99. package/dist/cli/commands/init.d.ts +1 -0
  100. package/dist/cli/commands/init.js +129 -0
  101. package/dist/cli/commands/init.js.map +1 -0
  102. package/dist/cli/commands/rename.d.ts +7 -0
  103. package/dist/cli/commands/rename.js +188 -0
  104. package/dist/cli/commands/rename.js.map +1 -0
  105. package/dist/cli/commands/upgrade.d.ts +6 -0
  106. package/dist/cli/commands/upgrade.js +66 -0
  107. package/dist/cli/commands/upgrade.js.map +1 -0
  108. package/dist/cli/index.d.ts +1 -0
  109. package/dist/cli/index.js +52 -0
  110. package/dist/cli/index.js.map +1 -0
  111. package/dist/cli/utils/assets.d.ts +3 -0
  112. package/dist/cli/utils/assets.js +20 -0
  113. package/dist/cli/utils/assets.js.map +1 -0
  114. package/dist/cli/utils/install-assets.d.ts +39 -0
  115. package/dist/cli/utils/install-assets.js +141 -0
  116. package/dist/cli/utils/install-assets.js.map +1 -0
  117. package/dist/cli/utils/lang.d.ts +1 -0
  118. package/dist/cli/utils/lang.js +32 -0
  119. package/dist/cli/utils/lang.js.map +1 -0
  120. package/dist/cli/utils/managed-assets.d.ts +9 -0
  121. package/dist/cli/utils/managed-assets.js +20 -0
  122. package/dist/cli/utils/managed-assets.js.map +1 -0
  123. package/dist/cli/utils/mcp-register.d.ts +2 -0
  124. package/dist/cli/utils/mcp-register.js +132 -0
  125. package/dist/cli/utils/mcp-register.js.map +1 -0
  126. package/dist/cli/utils/sync-vault.d.ts +14 -0
  127. package/dist/cli/utils/sync-vault.js +132 -0
  128. package/dist/cli/utils/sync-vault.js.map +1 -0
  129. package/dist/cli/utils/ui.d.ts +14 -0
  130. package/dist/cli/utils/ui.js +78 -0
  131. package/dist/cli/utils/ui.js.map +1 -0
  132. package/dist/cli/utils/version.d.ts +1 -0
  133. package/dist/cli/utils/version.js +4 -0
  134. package/dist/cli/utils/version.js.map +1 -0
  135. package/dist/config.d.ts +127 -0
  136. package/dist/config.js +356 -0
  137. package/dist/config.js.map +1 -0
  138. package/dist/core.d.ts +106 -0
  139. package/dist/core.js +286 -0
  140. package/dist/core.js.map +1 -0
  141. package/dist/db/consolidation.d.ts +14 -0
  142. package/dist/db/consolidation.js +28 -0
  143. package/dist/db/consolidation.js.map +1 -0
  144. package/dist/db/index.d.ts +22 -0
  145. package/dist/db/index.js +39 -0
  146. package/dist/db/index.js.map +1 -0
  147. package/dist/db/schema.d.ts +7 -0
  148. package/dist/db/schema.js +175 -0
  149. package/dist/db/schema.js.map +1 -0
  150. package/dist/index.d.ts +3 -0
  151. package/dist/index.js +5 -0
  152. package/dist/index.js.map +1 -0
  153. package/dist/server.d.ts +6 -0
  154. package/dist/server.js +303 -0
  155. package/dist/server.js.map +1 -0
  156. package/dist/services/capture.d.ts +101 -0
  157. package/dist/services/capture.js +297 -0
  158. package/dist/services/capture.js.map +1 -0
  159. package/dist/services/enhance.d.ts +51 -0
  160. package/dist/services/enhance.js +184 -0
  161. package/dist/services/enhance.js.map +1 -0
  162. package/dist/services/layer0.d.ts +24 -0
  163. package/dist/services/layer0.js +90 -0
  164. package/dist/services/layer0.js.map +1 -0
  165. package/dist/services/maintenance.d.ts +27 -0
  166. package/dist/services/maintenance.js +73 -0
  167. package/dist/services/maintenance.js.map +1 -0
  168. package/dist/services/retrieval.d.ts +120 -0
  169. package/dist/services/retrieval.js +571 -0
  170. package/dist/services/retrieval.js.map +1 -0
  171. package/dist/services/startup.d.ts +28 -0
  172. package/dist/services/startup.js +112 -0
  173. package/dist/services/startup.js.map +1 -0
  174. package/dist/skill-context/ask-global.d.ts +8 -0
  175. package/dist/skill-context/ask-global.js +21 -0
  176. package/dist/skill-context/ask-global.js.map +1 -0
  177. package/dist/skill-context/base.d.ts +48 -0
  178. package/dist/skill-context/base.js +5 -0
  179. package/dist/skill-context/base.js.map +1 -0
  180. package/dist/skill-context/daily-global.d.ts +8 -0
  181. package/dist/skill-context/daily-global.js +25 -0
  182. package/dist/skill-context/daily-global.js.map +1 -0
  183. package/dist/skill-context/index.d.ts +32 -0
  184. package/dist/skill-context/index.js +171 -0
  185. package/dist/skill-context/index.js.map +1 -0
  186. package/dist/skill-context/knowledge-strict.d.ts +8 -0
  187. package/dist/skill-context/knowledge-strict.js +26 -0
  188. package/dist/skill-context/knowledge-strict.js.map +1 -0
  189. package/dist/skill-context/review-strict.d.ts +8 -0
  190. package/dist/skill-context/review-strict.js +26 -0
  191. package/dist/skill-context/review-strict.js.map +1 -0
  192. package/dist/skill-context/revise-strict.d.ts +8 -0
  193. package/dist/skill-context/revise-strict.js +26 -0
  194. package/dist/skill-context/revise-strict.js.map +1 -0
  195. package/dist/skill-context/seed-profiles.d.ts +21 -0
  196. package/dist/skill-context/seed-profiles.js +80 -0
  197. package/dist/skill-context/seed-profiles.js.map +1 -0
  198. package/dist/types.d.ts +165 -0
  199. package/dist/types.js +76 -0
  200. package/dist/types.js.map +1 -0
  201. package/dist/utils/context-policy.d.ts +57 -0
  202. package/dist/utils/context-policy.js +333 -0
  203. package/dist/utils/context-policy.js.map +1 -0
  204. package/dist/utils/scan-state.d.ts +41 -0
  205. package/dist/utils/scan-state.js +79 -0
  206. package/dist/utils/scan-state.js.map +1 -0
  207. package/dist/utils/segmenter.d.ts +19 -0
  208. package/dist/utils/segmenter.js +75 -0
  209. package/dist/utils/segmenter.js.map +1 -0
  210. package/dist/utils/shared.d.ts +103 -0
  211. package/dist/utils/shared.js +313 -0
  212. package/dist/utils/shared.js.map +1 -0
  213. package/dist/utils/vault-indexer.d.ts +53 -0
  214. package/dist/utils/vault-indexer.js +256 -0
  215. package/dist/utils/vault-indexer.js.map +1 -0
  216. package/package.json +59 -0
@@ -0,0 +1,103 @@
1
+ /**
2
+ * shared.ts — 通用工具函数。
3
+ *
4
+ * Provides utility functions used by all other modules.
5
+ */
6
+ import type Database from 'better-sqlite3';
7
+ export declare const SESSION_ID_ENV_KEYS: readonly ["LIFEOS_SESSION_ID", "CLAUDE_SESSION_ID", "CODEX_SESSION_ID", "OPENCODE_SESSION_ID"];
8
+ export declare const ALLOWED_COUNT_TABLES: Set<string>;
9
+ export { VALID_ENTRY_TYPES, KEY_ENTRY_TYPES, ACTIVE_DOC_TARGETS } from '../types.js';
10
+ export { daysAgo, formatDateShort } from '../types.js';
11
+ export declare const RULE_KEY_DETAIL_FIELDS: readonly ["rule_key", "preference_slot", "constraint_key"];
12
+ export declare const RULE_KEY_PREFIXES: Record<string, string>;
13
+ export declare const TEMPORARY_PREFERENCE_KEYWORDS: readonly ["这次", "暂时", "先这样", "本周", "今天", "当前先", "这一轮", "这两天"];
14
+ export declare const STABLE_PREFERENCE_KEYWORDS: readonly ["长期", "一直", "固定", "习惯", "通常", "默认"];
15
+ export declare const DEFAULT_TEMPORARY_PREFERENCE_DAYS = 14;
16
+ export declare const ALL_TIME_DAYS = 3650;
17
+ export declare const FALLBACK_THRESHOLD = 3;
18
+ export declare const SUMMARY_MAX_LEN = 500;
19
+ export declare const BUCKET_TYPE_MAP: Record<string, Set<string>>;
20
+ /**
21
+ * Resolve a session ID from the provided value or environment variables.
22
+ * Returns 'untracked' when no valid session ID can be found.
23
+ */
24
+ export declare function resolveSessionId(sessionId?: string | null): string;
25
+ /**
26
+ * Coerce various input types to a Date object.
27
+ * - No argument → current UTC time
28
+ * - Date → returned as-is
29
+ * - string → parsed via Date constructor (ISO format)
30
+ * - Other types → throw TypeError
31
+ */
32
+ export declare function coerceNow(now?: Date | string | null): Date;
33
+ /**
34
+ * Coerce a value to a list of strings.
35
+ * Handles null/undefined, raw arrays, JSON array strings, and plain strings.
36
+ */
37
+ export declare function loadsJsonList(value: string | string[] | null | undefined): string[];
38
+ /**
39
+ * Parse a JSON string into a plain object.
40
+ * Returns an empty object on failure or if the result is not an object.
41
+ */
42
+ export declare function parseDetailObject(detail: string | null | undefined): Record<string, unknown>;
43
+ /**
44
+ * Estimate the token count for a text string.
45
+ * CJK characters count as 1 token each.
46
+ * Latin words count as 1.3 tokens each (ceiling).
47
+ * Other non-whitespace characters count as 0.5 tokens each (floor).
48
+ */
49
+ export declare function estimateTokens(text: string): number;
50
+ /**
51
+ * Return true if the text contains at least one CJK character (U+4E00–U+9FFF).
52
+ */
53
+ export declare function containsCjk(text: string): boolean;
54
+ /**
55
+ * Strip [[ and ]] from a wikilink value, trimming whitespace.
56
+ * Returns null for null input.
57
+ */
58
+ export declare function normalizeWikilinkValue(value: unknown): string | null;
59
+ /**
60
+ * Compact text to at most `limit` characters, appending '...' if truncated.
61
+ * Normalizes internal whitespace. Returns '暂无摘要' for empty input.
62
+ */
63
+ export declare function compactText(text: string | null | undefined, limit?: number): string;
64
+ /**
65
+ * Normalize whitespace and truncate to `limit` characters (no ellipsis).
66
+ * Returns empty string for empty/null input.
67
+ */
68
+ export declare function normalizeRuleSummary(text: string | null | undefined, limit?: number): string;
69
+ /**
70
+ * Build a default rule key from entry type and summary text.
71
+ * Returns null if the entry type has no prefix or the summary is empty.
72
+ */
73
+ export declare function buildDefaultRuleKey(entryType: string, text: string): string | null;
74
+ /**
75
+ * Extract an explicit rule key value from a detail object.
76
+ * Checks rule_key, preference_slot, constraint_key in order.
77
+ */
78
+ export declare function extractRuleKeyValue(detailObj: Record<string, unknown> | null | undefined): string | null;
79
+ /**
80
+ * Resolve the final rule key for an entry.
81
+ * Prefers explicit keys in detail_obj, falls back to building from entry type + summary.
82
+ */
83
+ export declare function resolveRuleKey(entryType: string, summary: string, detailObj?: Record<string, unknown> | null): string | null;
84
+ type TemporaryPreferenceResult = {
85
+ temporary: boolean;
86
+ expiresInDays?: number;
87
+ expiresAt?: string;
88
+ temporarySource?: string;
89
+ };
90
+ /**
91
+ * Infer whether a preference entry is temporary based on text keywords
92
+ * or explicit fields in the detail object.
93
+ */
94
+ export declare function inferTemporaryPreference(text: string, detailObj?: Record<string, unknown> | null): TemporaryPreferenceResult;
95
+ /**
96
+ * Count rows in an allowed table, with optional WHERE clause.
97
+ * Throws if the table name is not in ALLOWED_COUNT_TABLES.
98
+ */
99
+ export declare function countRows(conn: Database.Database, table: string, whereSql?: string, params?: unknown[]): number;
100
+ /**
101
+ * Return true if the summary represents an archive summary entry.
102
+ */
103
+ export declare function isArchiveSummary(summary: unknown, entryType?: string): boolean;
@@ -0,0 +1,313 @@
1
+ /**
2
+ * shared.ts — 通用工具函数。
3
+ *
4
+ * Provides utility functions used by all other modules.
5
+ */
6
+ // ─── Constants ────────────────────────────────────────────────────────────────
7
+ export const SESSION_ID_ENV_KEYS = [
8
+ 'LIFEOS_SESSION_ID',
9
+ 'CLAUDE_SESSION_ID',
10
+ 'CODEX_SESSION_ID',
11
+ 'OPENCODE_SESSION_ID',
12
+ ];
13
+ export const ALLOWED_COUNT_TABLES = new Set([
14
+ 'vault_index',
15
+ 'enhance_queue',
16
+ 'session_log',
17
+ ]);
18
+ export { VALID_ENTRY_TYPES, KEY_ENTRY_TYPES, ACTIVE_DOC_TARGETS } from '../types.js';
19
+ export { daysAgo, formatDateShort } from '../types.js';
20
+ export const RULE_KEY_DETAIL_FIELDS = ['rule_key', 'preference_slot', 'constraint_key'];
21
+ export const RULE_KEY_PREFIXES = {
22
+ decision: 'decision',
23
+ correction: 'correction',
24
+ preference: 'prefer',
25
+ };
26
+ export const TEMPORARY_PREFERENCE_KEYWORDS = [
27
+ '这次',
28
+ '暂时',
29
+ '先这样',
30
+ '本周',
31
+ '今天',
32
+ '当前先',
33
+ '这一轮',
34
+ '这两天',
35
+ ];
36
+ export const STABLE_PREFERENCE_KEYWORDS = ['长期', '一直', '固定', '习惯', '通常', '默认'];
37
+ export const DEFAULT_TEMPORARY_PREFERENCE_DAYS = 14;
38
+ export const ALL_TIME_DAYS = 3650;
39
+ export const FALLBACK_THRESHOLD = 3;
40
+ export const SUMMARY_MAX_LEN = 500;
41
+ export const BUCKET_TYPE_MAP = {
42
+ daily: new Set(['daily', 'diary']),
43
+ draft: new Set(['draft']),
44
+ project: new Set(['project']),
45
+ research: new Set(['research']),
46
+ knowledge: new Set(['knowledge', 'note', 'revise-record']),
47
+ resource: new Set(['resource']),
48
+ };
49
+ // ─── Session ──────────────────────────────────────────────────────────────────
50
+ /**
51
+ * Resolve a session ID from the provided value or environment variables.
52
+ * Returns 'untracked' when no valid session ID can be found.
53
+ */
54
+ export function resolveSessionId(sessionId) {
55
+ if (sessionId != null && String(sessionId).trim()) {
56
+ return String(sessionId).trim();
57
+ }
58
+ for (const envKey of SESSION_ID_ENV_KEYS) {
59
+ const value = process.env[envKey];
60
+ if (value?.trim()) {
61
+ return value.trim();
62
+ }
63
+ }
64
+ return 'untracked';
65
+ }
66
+ // ─── Time ─────────────────────────────────────────────────────────────────────
67
+ /**
68
+ * Coerce various input types to a Date object.
69
+ * - No argument → current UTC time
70
+ * - Date → returned as-is
71
+ * - string → parsed via Date constructor (ISO format)
72
+ * - Other types → throw TypeError
73
+ */
74
+ export function coerceNow(now) {
75
+ if (now == null) {
76
+ return new Date();
77
+ }
78
+ if (now instanceof Date) {
79
+ return now;
80
+ }
81
+ if (typeof now === 'string') {
82
+ const parsed = new Date(now);
83
+ if (Number.isNaN(parsed.getTime())) {
84
+ throw new TypeError(`Cannot parse date string: ${now}`);
85
+ }
86
+ return parsed;
87
+ }
88
+ throw new TypeError(`Unsupported time type: ${typeof now}`);
89
+ }
90
+ // ─── JSON / List helpers ──────────────────────────────────────────────────────
91
+ /**
92
+ * Coerce a value to a list of strings.
93
+ * Handles null/undefined, raw arrays, JSON array strings, and plain strings.
94
+ */
95
+ export function loadsJsonList(value) {
96
+ if (value == null)
97
+ return [];
98
+ if (Array.isArray(value)) {
99
+ return value.filter((item) => item != null).map((item) => String(item));
100
+ }
101
+ if (typeof value === 'string') {
102
+ const stripped = value.trim();
103
+ if (!stripped)
104
+ return [];
105
+ let parsed;
106
+ try {
107
+ parsed = JSON.parse(stripped);
108
+ }
109
+ catch {
110
+ return [stripped];
111
+ }
112
+ if (parsed === null)
113
+ return [];
114
+ if (Array.isArray(parsed)) {
115
+ return parsed.filter((item) => item != null).map((item) => String(item));
116
+ }
117
+ return [String(parsed)];
118
+ }
119
+ return [String(value)];
120
+ }
121
+ /**
122
+ * Parse a JSON string into a plain object.
123
+ * Returns an empty object on failure or if the result is not an object.
124
+ */
125
+ export function parseDetailObject(detail) {
126
+ if (!detail)
127
+ return {};
128
+ try {
129
+ const parsed = JSON.parse(detail);
130
+ if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
131
+ return parsed;
132
+ }
133
+ return {};
134
+ }
135
+ catch {
136
+ return {};
137
+ }
138
+ }
139
+ // ─── Text / Token helpers ─────────────────────────────────────────────────────
140
+ /**
141
+ * Estimate the token count for a text string.
142
+ * CJK characters count as 1 token each.
143
+ * Latin words count as 1.3 tokens each (ceiling).
144
+ * Other non-whitespace characters count as 0.5 tokens each (floor).
145
+ */
146
+ export function estimateTokens(text) {
147
+ if (!text.trim())
148
+ return 0;
149
+ const cjkCount = [...text].filter((ch) => ch >= '\u4e00' && ch <= '\u9fff').length;
150
+ const latinWords = (text.match(/[A-Za-z0-9_]+/g) ?? []).length;
151
+ const otherChars = (text.match(/[^\sA-Za-z0-9_\u4e00-\u9fff]/g) ?? []).length;
152
+ return cjkCount + Math.ceil(latinWords * 1.3) + Math.max(Math.floor(otherChars / 2), 0);
153
+ }
154
+ /**
155
+ * Return true if the text contains at least one CJK character (U+4E00–U+9FFF).
156
+ */
157
+ export function containsCjk(text) {
158
+ return [...text].some((ch) => ch >= '\u4e00' && ch <= '\u9fff');
159
+ }
160
+ /**
161
+ * Strip [[ and ]] from a wikilink value, trimming whitespace.
162
+ * Returns null for null input.
163
+ */
164
+ export function normalizeWikilinkValue(value) {
165
+ if (value == null)
166
+ return null;
167
+ let normalized = String(value).trim();
168
+ if (normalized.startsWith('[[') && normalized.endsWith(']]')) {
169
+ normalized = normalized.slice(2, -2).trim();
170
+ }
171
+ return normalized;
172
+ }
173
+ /**
174
+ * Compact text to at most `limit` characters, appending '...' if truncated.
175
+ * Normalizes internal whitespace. Returns '暂无摘要' for empty input.
176
+ */
177
+ export function compactText(text, limit = 160) {
178
+ const normalized = (text ?? '').replace(/\s+/g, ' ').trim();
179
+ if (!normalized)
180
+ return '暂无摘要';
181
+ if (normalized.length <= limit)
182
+ return normalized;
183
+ return `${normalized.slice(0, Math.max(limit - 3, 0)).trimEnd()}...`;
184
+ }
185
+ /**
186
+ * Normalize whitespace and truncate to `limit` characters (no ellipsis).
187
+ * Returns empty string for empty/null input.
188
+ */
189
+ export function normalizeRuleSummary(text, limit = 160) {
190
+ const normalized = String(text ?? '')
191
+ .replace(/\s+/g, ' ')
192
+ .trim();
193
+ if (!normalized)
194
+ return '';
195
+ if (normalized.length <= limit)
196
+ return normalized;
197
+ return normalized.slice(0, limit).trimEnd();
198
+ }
199
+ // ─── Rule key helpers ─────────────────────────────────────────────────────────
200
+ /**
201
+ * Build a default rule key from entry type and summary text.
202
+ * Returns null if the entry type has no prefix or the summary is empty.
203
+ */
204
+ export function buildDefaultRuleKey(entryType, text) {
205
+ const prefix = RULE_KEY_PREFIXES[entryType];
206
+ const normalized = normalizeRuleSummary(text);
207
+ if (!prefix || !normalized)
208
+ return null;
209
+ return `${prefix}:${normalized}`;
210
+ }
211
+ /**
212
+ * Extract an explicit rule key value from a detail object.
213
+ * Checks rule_key, preference_slot, constraint_key in order.
214
+ */
215
+ export function extractRuleKeyValue(detailObj) {
216
+ const payload = detailObj ?? {};
217
+ for (const field of RULE_KEY_DETAIL_FIELDS) {
218
+ const value = payload[field];
219
+ if (value)
220
+ return String(value).trim();
221
+ }
222
+ return null;
223
+ }
224
+ /**
225
+ * Resolve the final rule key for an entry.
226
+ * Prefers explicit keys in detail_obj, falls back to building from entry type + summary.
227
+ */
228
+ export function resolveRuleKey(entryType, summary, detailObj) {
229
+ const explicit = extractRuleKeyValue(detailObj);
230
+ if (explicit)
231
+ return explicit;
232
+ return buildDefaultRuleKey(entryType, summary);
233
+ }
234
+ function coerceBoolValue(value) {
235
+ if (typeof value === 'boolean')
236
+ return value;
237
+ if (typeof value === 'string') {
238
+ const lower = value.toLowerCase().trim();
239
+ if (lower === 'false' || lower === '0' || lower === 'no')
240
+ return false;
241
+ return Boolean(value);
242
+ }
243
+ return Boolean(value);
244
+ }
245
+ /**
246
+ * Infer whether a preference entry is temporary based on text keywords
247
+ * or explicit fields in the detail object.
248
+ */
249
+ export function inferTemporaryPreference(text, detailObj) {
250
+ const payload = detailObj ?? {};
251
+ // Check for explicit fields in detail_obj
252
+ const hasExplicitFields = ['temporary', 'expires_at', 'expires_in_days', 'temporary_source'].some((key) => payload[key] != null);
253
+ if (hasExplicitFields) {
254
+ const result = { temporary: true };
255
+ if (payload.temporary != null) {
256
+ result.temporary = coerceBoolValue(payload.temporary);
257
+ }
258
+ const rawExpiresInDays = payload.expires_in_days;
259
+ if (rawExpiresInDays != null) {
260
+ const days = Number.parseInt(String(rawExpiresInDays), 10);
261
+ if (!Number.isNaN(days))
262
+ result.expiresInDays = days;
263
+ }
264
+ if (payload.expires_at) {
265
+ result.expiresAt = String(payload.expires_at);
266
+ }
267
+ if (payload.temporary_source) {
268
+ result.temporarySource = String(payload.temporary_source);
269
+ }
270
+ else {
271
+ result.temporarySource = 'explicit';
272
+ }
273
+ return result;
274
+ }
275
+ // Keyword-based inference
276
+ const normalized = normalizeRuleSummary(text);
277
+ if (STABLE_PREFERENCE_KEYWORDS.some((kw) => normalized.includes(kw))) {
278
+ return { temporary: false };
279
+ }
280
+ if (TEMPORARY_PREFERENCE_KEYWORDS.some((kw) => normalized.includes(kw))) {
281
+ return {
282
+ temporary: true,
283
+ expiresInDays: DEFAULT_TEMPORARY_PREFERENCE_DAYS,
284
+ temporarySource: 'keyword_fallback',
285
+ };
286
+ }
287
+ return { temporary: false };
288
+ }
289
+ // ─── Database helpers ─────────────────────────────────────────────────────────
290
+ /**
291
+ * Count rows in an allowed table, with optional WHERE clause.
292
+ * Throws if the table name is not in ALLOWED_COUNT_TABLES.
293
+ */
294
+ export function countRows(conn, table, whereSql = '', params = []) {
295
+ if (!ALLOWED_COUNT_TABLES.has(table)) {
296
+ throw new Error(`Invalid table: ${table}`);
297
+ }
298
+ let sql = `SELECT COUNT(*) FROM ${table}`;
299
+ if (whereSql)
300
+ sql += ` WHERE ${whereSql}`;
301
+ const row = conn.prepare(sql).get(params);
302
+ return row ? Number(row['COUNT(*)']) : 0;
303
+ }
304
+ // ─── Archive helpers ──────────────────────────────────────────────────────────
305
+ /**
306
+ * Return true if the summary represents an archive summary entry.
307
+ */
308
+ export function isArchiveSummary(summary, entryType) {
309
+ if (entryType === 'archive_summary')
310
+ return true;
311
+ return String(summary ?? '').startsWith('归档摘要:');
312
+ }
313
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/utils/shared.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * vault-indexer.ts — Vault 索引器。
3
+ *
4
+ * Scans Vault markdown files, parses frontmatter, and writes to the
5
+ * SQLite index.
6
+ */
7
+ import { VaultConfig } from '../config.js';
8
+ export interface ParsedMarkdown {
9
+ title: string;
10
+ type: string | null;
11
+ status: string | null;
12
+ domain: string | null;
13
+ category: string | null;
14
+ tags: string;
15
+ aliases: string;
16
+ summary: string;
17
+ semanticSummary: string | null;
18
+ searchHints: string;
19
+ wikilinks: string;
20
+ backlinks: string;
21
+ sectionHeads: string;
22
+ contentHash: string;
23
+ }
24
+ export interface ScanResult {
25
+ indexed: number;
26
+ skipped: number;
27
+ }
28
+ export interface IndexResult {
29
+ status: 'indexed' | 'skipped' | 'removed';
30
+ filePath?: string;
31
+ reason?: string;
32
+ }
33
+ /**
34
+ * Determine whether a vault-relative file path should be indexed.
35
+ * Returns true only if path ends in .md, matches an included prefix,
36
+ * and does not match an excluded prefix.
37
+ */
38
+ export declare function shouldIndex(relativePath: string, config?: VaultConfig): boolean;
39
+ /**
40
+ * Parse a markdown file's content, extracting frontmatter and body metadata.
41
+ * Returns null if the file has no valid frontmatter.
42
+ */
43
+ export declare function parseMarkdown(content: string, fileName: string): ParsedMarkdown | null;
44
+ /**
45
+ * Scan all .md files in the vault and index them into the SQLite database.
46
+ * Skips files that don't match scan rules or lack valid frontmatter.
47
+ */
48
+ export declare function fullScan(vaultRoot: string, dbPath: string, config?: VaultConfig): ScanResult;
49
+ /**
50
+ * Index or re-index a single file. Handles absolute or relative paths.
51
+ * If the file has been deleted, removes its entry from the index.
52
+ */
53
+ export declare function indexSingleFile(vaultRoot: string, dbPath: string, filePath: string, config?: VaultConfig): IndexResult;