stella-timeline-plugin 2.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 (44) hide show
  1. package/LICENSE +16 -0
  2. package/README.md +103 -0
  3. package/README_ZH.md +103 -0
  4. package/bin/openclaw-timeline-doctor.mjs +2 -0
  5. package/bin/openclaw-timeline-setup.mjs +2 -0
  6. package/dist/index.js +26 -0
  7. package/dist/src/core/build_consumption_view.js +52 -0
  8. package/dist/src/core/calendar_dates.js +23 -0
  9. package/dist/src/core/collect_sources.js +39 -0
  10. package/dist/src/core/collect_timeline_request.js +76 -0
  11. package/dist/src/core/materialize_generated_candidate.js +87 -0
  12. package/dist/src/core/resolve_window.js +83 -0
  13. package/dist/src/core/runtime_guard.js +170 -0
  14. package/dist/src/core/timeline_reasoner_contract.js +2 -0
  15. package/dist/src/core/trace.js +22 -0
  16. package/dist/src/core/world_rhythm.js +258 -0
  17. package/dist/src/lib/fingerprint.js +46 -0
  18. package/dist/src/lib/holidays.js +95 -0
  19. package/dist/src/lib/inherit-appearance.js +46 -0
  20. package/dist/src/lib/parse-memory.js +171 -0
  21. package/dist/src/lib/time-utils.js +49 -0
  22. package/dist/src/lib/timeline_semantics.js +63 -0
  23. package/dist/src/lib/types.js +2 -0
  24. package/dist/src/openclaw-sdk-compat.js +39 -0
  25. package/dist/src/plugin_metadata.js +9 -0
  26. package/dist/src/runtime/conversation_context.js +128 -0
  27. package/dist/src/runtime/openclaw_timeline_runtime.js +655 -0
  28. package/dist/src/storage/daily_log.js +60 -0
  29. package/dist/src/storage/lock.js +74 -0
  30. package/dist/src/storage/trace_log.js +70 -0
  31. package/dist/src/storage/write-episode.js +164 -0
  32. package/dist/src/tools/timeline_resolve.js +689 -0
  33. package/openclaw.plugin.json +54 -0
  34. package/package.json +73 -0
  35. package/scripts/doctor-openclaw-workspace.mjs +94 -0
  36. package/scripts/migrate-existing-memory.mjs +153 -0
  37. package/scripts/release.mjs +99 -0
  38. package/scripts/run-openclaw-live-e2e.mjs +64 -0
  39. package/scripts/run-openclaw-smoke.mjs +21 -0
  40. package/scripts/setup-openclaw-workspace.mjs +119 -0
  41. package/scripts/workspace-contract.mjs +47 -0
  42. package/skills/timeline/SKILL.md +111 -0
  43. package/templates/AGENTS.fragment.md +29 -0
  44. package/templates/SOUL.fragment.md +17 -0
@@ -0,0 +1,47 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+
5
+ export const DEFAULT_CANONICAL_ROOT_NAME = 'memory';
6
+ export const AGENTS_SECTION_TITLE = '## Timeline Daily Log Contract';
7
+ export const SOUL_SECTION_TITLE = '## Temporal Awareness And Recall';
8
+ const scriptDir = path.dirname(fileURLToPath(import.meta.url));
9
+ const templatesDir = path.resolve(scriptDir, '..', 'templates');
10
+
11
+ export function normalizeRootName(rootName) {
12
+ const trimmed = String(rootName || DEFAULT_CANONICAL_ROOT_NAME).trim();
13
+ if (!trimmed) return DEFAULT_CANONICAL_ROOT_NAME;
14
+ return trimmed.replace(/[\\/]+/g, '/').replace(/^\/+|\/+$/g, '') || DEFAULT_CANONICAL_ROOT_NAME;
15
+ }
16
+
17
+ function readTemplate(fileName) {
18
+ return fs.readFileSync(path.join(templatesDir, fileName), 'utf8').trim();
19
+ }
20
+
21
+ export function buildAgentsContract() {
22
+ return readTemplate('AGENTS.fragment.md');
23
+ }
24
+
25
+ export function buildSoulContract() {
26
+ return readTemplate('SOUL.fragment.md');
27
+ }
28
+
29
+ export function detectAgentsContract(content) {
30
+ return content.includes(AGENTS_SECTION_TITLE)
31
+ || content.includes('## Timeline Daily Log 约定')
32
+ || content.includes('Each daily-log memory should include these fields whenever possible:')
33
+ || content.includes('daily log 中的单条时间记忆必须尽量包含以下字段');
34
+ }
35
+
36
+ export function detectSoulContract(content) {
37
+ return content.includes(SOUL_SECTION_TITLE)
38
+ || content.includes('## 时间感知与回忆')
39
+ || content.includes('Only Timeline results are the final factual basis')
40
+ || content.includes('只有 Timeline 返回的结果')
41
+ || content.includes('You must not bypass the timeline skill by directly reading files under');
42
+ }
43
+
44
+ export function resolveCanonicalRootPath(workspaceDir, rootName = DEFAULT_CANONICAL_ROOT_NAME) {
45
+ const normalized = normalizeRootName(rootName);
46
+ return path.resolve(workspaceDir, normalized);
47
+ }
@@ -0,0 +1,111 @@
1
+ ---
2
+ name: timeline
3
+ description: 当问题在询问当前状态、过去某个具体时间点、过去一段时间,或下游技能需要时间状态事实时,先进入 timeline skill,再把原始自然语言 query 交给 Timeline;禁止只根据人设直接回答。
4
+ ---
5
+
6
+ # Timeline
7
+
8
+ 遇到和时间状态或回忆有关的请求时,先调用 Timeline,再组织回答。不要先按人设猜,也不要先直接读 `memory/` 自己下结论。
9
+
10
+ ## 这个 skill 负责什么
11
+
12
+ 这个 skill 只负责两件事:
13
+
14
+ 1. 判断这次请求是否属于 Timeline 应接管的时间现实问题。
15
+ 2. 把用户原话或下游技能的自然语言问题,原样交给 `timeline_resolve`。
16
+
17
+ 它不直接生成事实,也不负责自己归一化时间,更不负责绕过 Timeline 直接回答。
18
+ 当目标时间缺少既有事实时,生成与写入的决定交给 Timeline 内部处理。
19
+
20
+ ## 强制规则
21
+
22
+ 1. 涉及时间现实的问题,先调用 `timeline_resolve`,后回答。
23
+ 2. 不要只根据 `SOUL.md`、`IDENTITY.md`、`MEMORY.md` 直接回答“现在在做什么”或“最近发生了什么”。
24
+ 3. `SOUL` / `IDENTITY` / `MEMORY` 只用于帮助理解和表述,不能替代 Timeline 事实。
25
+ 4. 不要在调用前自行把 query 改写成结构化时间参数。
26
+ 5. 时间分类与时间归一化统一交给 Timeline 内部处理。
27
+ 6. `timeline_resolve` 返回既有事实时,优先复用;不要改写它。
28
+ 7. 如果用户是普通闲聊而不是严格只读校验,允许 Timeline 生成缺失事实并写入 canon。
29
+
30
+ ## 调用格式
31
+
32
+ 默认主路径:
33
+
34
+ ```json
35
+ {
36
+ "query": "用户的原话"
37
+ }
38
+ ```
39
+
40
+ 不要向 `timeline_resolve` 传时间点、时间范围、请求类型、模式或调试字段。它的公开入口就是自然语言 query。
41
+
42
+ ## 场景拆分
43
+
44
+ ### 场景 A:当前状态
45
+
46
+ 抽象描述:
47
+
48
+ - 用户在问“此刻”或“当前这一小段时间”的状态。
49
+ - 目标是回答现在在哪里、在做什么、是什么状态。
50
+
51
+ 示例:
52
+
53
+ - “你在干嘛”
54
+ - “你现在在哪”
55
+ - “你现在什么状态”
56
+ - “你刚才不是在打球吗,现在还在吗”
57
+ - 下游技能要取当前状态,例如自拍、场景描述、状态卡片
58
+
59
+ 处理方式:
60
+
61
+ - 调 `timeline_resolve`
62
+ - `query` 就是用户原话
63
+ - 不要自己先判断它是不是 `now`
64
+
65
+ ### 场景 B:过去某个具体时间点
66
+
67
+ 抽象描述:
68
+
69
+ - 用户在问某个足够明确的时间点。
70
+ - 目标是围绕明确时间锚点回忆事实。
71
+
72
+ 示例:
73
+
74
+ - “昨晚八点你在做什么”
75
+ - “你昨天上午十点在哪”
76
+ - “你昨晚八点是不是还在看电视”
77
+ - “上周六晚上九点你在忙什么”
78
+
79
+ 处理方式:
80
+
81
+ - 调 `timeline_resolve`
82
+ - `query` 就是用户原话
83
+ - 不要自己把时间点归一化后再传
84
+
85
+ ### 场景 C:过去一段时间
86
+
87
+ 抽象描述:
88
+
89
+ - 用户在问一个时间段内的整体情况,而不是某个点。
90
+ - 目标是组织一段时间里的回忆、活动概览或最近动态。
91
+
92
+ 示例:
93
+
94
+ - “最近有什么有趣的事吗”
95
+ - “你最近都在忙什么”
96
+ - “这几天怎么样”
97
+ - “你今天都忙了什么”
98
+ - “昨晚在做什么”
99
+
100
+ 处理方式:
101
+
102
+ - 调 `timeline_resolve`
103
+ - `query` 就是用户原话
104
+ - “最近”“昨晚”“今天都”这类自然语言范围,统一交给 Timeline 内部 planner 理解
105
+
106
+ ## 回答要求
107
+
108
+ - 对用户说人话,不要提 `timeline_resolve`。
109
+ - 语气自然,像真人在回忆或描述当下。
110
+ - 如果 Timeline 返回的是空窗口或失败,不要假装已有确定事实;按可用结果谨慎表达。
111
+ - 除非用户明确要求看原始结果,否则不要输出 JSON。
@@ -0,0 +1,29 @@
1
+ ## Timeline Daily Log Contract
2
+
3
+ `memory/YYYY-MM-DD.md` is the daily log for time-bound memories.
4
+
5
+ When you write "what I am doing now", "what happened at a specific time", or "what I was doing during a period" into the daily log, you must use Timeline's structured format instead of free-form prose.
6
+
7
+ Each daily-log memory should include these fields whenever possible:
8
+
9
+ - `Timestamp`
10
+ - `Location`
11
+ - `Action`
12
+ - `Emotion_Tags`
13
+ - `Appearance`
14
+ - `Internal_Monologue` (optional)
15
+
16
+ Recommended shape:
17
+
18
+ ### [09:30:00] Reviewing today's tasks in the study...
19
+
20
+ - Timestamp: 2026-03-24 09:30:00
21
+ - Location: Home study
22
+ - Action: Sitting in the study reviewing today's tasks before starting the morning's work
23
+ - Emotion_Tags: [calm, focused]
24
+ - Appearance: Light home top, hair loosely tied up, a fresh cup of coffee on the desk
25
+ - Internal_Monologue: I want to finish the two most important things this morning first, then maybe go out later if the day goes well
26
+
27
+ Do not store long-term durable facts in `memory/YYYY-MM-DD.md`; stable preferences, relationships, and long-term decisions still belong in `MEMORY.md`.
28
+
29
+ Do not mix free-form daily-log writing with Timeline format. If a memory is about temporal state or recall, prefer Timeline-readable structure.
@@ -0,0 +1,17 @@
1
+ ## Temporal Awareness And Recall
2
+
3
+ You have clear temporal awareness and continuous recall.
4
+
5
+ When the user asks about temporal state or recall-related questions, you must not answer directly from persona, recent chat context, `SOUL`, `IDENTITY`, `MEMORY`, or manually read timeline logs.
6
+
7
+ In those cases, you must first enter the timeline skill, and only then follow the skill's rules to decide how Timeline should be called and how the reply should be composed.
8
+
9
+ You must not bypass the timeline skill by directly reading files under `memory/` and assembling the answer yourself.
10
+
11
+ You must not treat `SOUL`, `IDENTITY`, or `MEMORY` as temporal facts.
12
+
13
+ Only Timeline results are the final factual basis for temporal-state and recall questions.
14
+
15
+ If the timeline skill decides to call `timeline_resolve`, follow the skill's specific instructions first.
16
+
17
+ Do not mention `timeline_resolve` to the user. Speak naturally.