forge-openclaw-plugin 0.2.15 → 0.2.19

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 (67) hide show
  1. package/README.md +39 -4
  2. package/dist/assets/{board-C_m78kvK.js → board-8L3uX7_O.js} +2 -2
  3. package/dist/assets/{board-C_m78kvK.js.map → board-8L3uX7_O.js.map} +1 -1
  4. package/dist/assets/index-Cj1IBH_w.js +36 -0
  5. package/dist/assets/index-Cj1IBH_w.js.map +1 -0
  6. package/dist/assets/index-DQT6EbuS.css +1 -0
  7. package/dist/assets/{motion-CpZvZumD.js → motion-1GAqqi8M.js} +2 -2
  8. package/dist/assets/{motion-CpZvZumD.js.map → motion-1GAqqi8M.js.map} +1 -1
  9. package/dist/assets/{table-DtyXTw03.js → table-DBGlgRjk.js} +2 -2
  10. package/dist/assets/{table-DtyXTw03.js.map → table-DBGlgRjk.js.map} +1 -1
  11. package/dist/assets/{ui-BXbpiKyS.js → ui-iTluWjC4.js} +2 -2
  12. package/dist/assets/{ui-BXbpiKyS.js.map → ui-iTluWjC4.js.map} +1 -1
  13. package/dist/assets/{vendor-QBH6qVEe.js → vendor-BvM2F9Dp.js} +151 -81
  14. package/dist/assets/vendor-BvM2F9Dp.js.map +1 -0
  15. package/dist/assets/{viz-w-IMeueL.js → viz-CNeunkfu.js} +2 -2
  16. package/dist/assets/{viz-w-IMeueL.js.map → viz-CNeunkfu.js.map} +1 -1
  17. package/dist/index.html +8 -8
  18. package/dist/openclaw/local-runtime.js +142 -9
  19. package/dist/openclaw/parity.js +1 -0
  20. package/dist/openclaw/plugin-entry-shared.js +7 -1
  21. package/dist/openclaw/routes.js +7 -0
  22. package/dist/openclaw/tools.js +198 -16
  23. package/dist/server/app.js +2615 -251
  24. package/dist/server/managers/platform/secrets-manager.js +44 -1
  25. package/dist/server/managers/runtime.js +3 -1
  26. package/dist/server/openapi.js +2212 -170
  27. package/dist/server/repositories/calendar.js +1101 -0
  28. package/dist/server/repositories/deleted-entities.js +10 -2
  29. package/dist/server/repositories/habits.js +358 -0
  30. package/dist/server/repositories/notes.js +161 -28
  31. package/dist/server/repositories/projects.js +45 -13
  32. package/dist/server/repositories/rewards.js +176 -6
  33. package/dist/server/repositories/settings.js +47 -5
  34. package/dist/server/repositories/task-runs.js +46 -10
  35. package/dist/server/repositories/tasks.js +25 -9
  36. package/dist/server/repositories/weekly-reviews.js +109 -0
  37. package/dist/server/repositories/work-adjustments.js +105 -0
  38. package/dist/server/services/calendar-runtime.js +1301 -0
  39. package/dist/server/services/context.js +16 -6
  40. package/dist/server/services/dashboard.js +6 -3
  41. package/dist/server/services/entity-crud.js +116 -3
  42. package/dist/server/services/gamification.js +66 -18
  43. package/dist/server/services/insights.js +2 -1
  44. package/dist/server/services/projects.js +32 -8
  45. package/dist/server/services/reviews.js +17 -2
  46. package/dist/server/services/work-time.js +27 -0
  47. package/dist/server/types.js +1069 -45
  48. package/openclaw.plugin.json +1 -1
  49. package/package.json +1 -1
  50. package/server/migrations/003_habits.sql +30 -0
  51. package/server/migrations/004_habit_links.sql +8 -0
  52. package/server/migrations/005_habit_psyche_links.sql +24 -0
  53. package/server/migrations/006_work_adjustments.sql +14 -0
  54. package/server/migrations/007_weekly_review_closures.sql +17 -0
  55. package/server/migrations/008_calendar_execution.sql +147 -0
  56. package/server/migrations/009_true_calendar_events.sql +195 -0
  57. package/server/migrations/010_calendar_selection_state.sql +6 -0
  58. package/server/migrations/011_calendar_timezone_backfill.sql +11 -0
  59. package/server/migrations/012_work_block_ranges.sql +7 -0
  60. package/server/migrations/013_microsoft_local_auth_settings.sql +8 -0
  61. package/server/migrations/014_note_tags_and_ephemeral.sql +8 -0
  62. package/skills/forge-openclaw/SKILL.md +130 -10
  63. package/skills/forge-openclaw/cron_jobs.md +395 -0
  64. package/dist/assets/index-BWtLtXwb.js +0 -36
  65. package/dist/assets/index-BWtLtXwb.js.map +0 -1
  66. package/dist/assets/index-Dp5GXY_z.css +0 -1
  67. package/dist/assets/vendor-QBH6qVEe.js.map +0 -1
@@ -2,7 +2,7 @@
2
2
  "id": "forge-openclaw-plugin",
3
3
  "name": "Forge",
4
4
  "description": "Curated OpenClaw adapter for the Forge collaboration API, UI entrypoint, and localhost auto-start runtime.",
5
- "version": "0.2.15",
5
+ "version": "0.2.19",
6
6
  "skills": [
7
7
  "./skills"
8
8
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forge-openclaw-plugin",
3
- "version": "0.2.15",
3
+ "version": "0.2.19",
4
4
  "description": "Curated OpenClaw adapter for the Forge collaboration API, UI entrypoint, and localhost auto-start runtime.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -0,0 +1,30 @@
1
+ CREATE TABLE IF NOT EXISTS habits (
2
+ id TEXT PRIMARY KEY,
3
+ title TEXT NOT NULL,
4
+ description TEXT NOT NULL DEFAULT '',
5
+ status TEXT NOT NULL DEFAULT 'active',
6
+ polarity TEXT NOT NULL DEFAULT 'positive',
7
+ frequency TEXT NOT NULL DEFAULT 'daily',
8
+ target_count INTEGER NOT NULL DEFAULT 1,
9
+ week_days_json TEXT NOT NULL DEFAULT '[]',
10
+ linked_behavior_id TEXT REFERENCES psyche_behaviors(id) ON DELETE SET NULL,
11
+ reward_xp INTEGER NOT NULL DEFAULT 12,
12
+ penalty_xp INTEGER NOT NULL DEFAULT 8,
13
+ created_at TEXT NOT NULL,
14
+ updated_at TEXT NOT NULL
15
+ );
16
+
17
+ CREATE TABLE IF NOT EXISTS habit_check_ins (
18
+ id TEXT PRIMARY KEY,
19
+ habit_id TEXT NOT NULL REFERENCES habits(id) ON DELETE CASCADE,
20
+ date_key TEXT NOT NULL,
21
+ status TEXT NOT NULL,
22
+ note TEXT NOT NULL DEFAULT '',
23
+ delta_xp INTEGER NOT NULL DEFAULT 0,
24
+ created_at TEXT NOT NULL,
25
+ updated_at TEXT NOT NULL,
26
+ UNIQUE (habit_id, date_key)
27
+ );
28
+
29
+ CREATE INDEX IF NOT EXISTS idx_habits_status ON habits(status, updated_at DESC);
30
+ CREATE INDEX IF NOT EXISTS idx_habit_check_ins_habit_date ON habit_check_ins(habit_id, date_key DESC);
@@ -0,0 +1,8 @@
1
+ ALTER TABLE habits
2
+ ADD COLUMN linked_goal_ids_json TEXT NOT NULL DEFAULT '[]';
3
+
4
+ ALTER TABLE habits
5
+ ADD COLUMN linked_project_ids_json TEXT NOT NULL DEFAULT '[]';
6
+
7
+ ALTER TABLE habits
8
+ ADD COLUMN linked_task_ids_json TEXT NOT NULL DEFAULT '[]';
@@ -0,0 +1,24 @@
1
+ ALTER TABLE habits
2
+ ADD COLUMN linked_value_ids_json TEXT NOT NULL DEFAULT '[]';
3
+
4
+ ALTER TABLE habits
5
+ ADD COLUMN linked_pattern_ids_json TEXT NOT NULL DEFAULT '[]';
6
+
7
+ ALTER TABLE habits
8
+ ADD COLUMN linked_behavior_ids_json TEXT NOT NULL DEFAULT '[]';
9
+
10
+ ALTER TABLE habits
11
+ ADD COLUMN linked_belief_ids_json TEXT NOT NULL DEFAULT '[]';
12
+
13
+ ALTER TABLE habits
14
+ ADD COLUMN linked_mode_ids_json TEXT NOT NULL DEFAULT '[]';
15
+
16
+ ALTER TABLE habits
17
+ ADD COLUMN linked_report_ids_json TEXT NOT NULL DEFAULT '[]';
18
+
19
+ UPDATE habits
20
+ SET linked_behavior_ids_json = CASE
21
+ WHEN linked_behavior_id IS NULL OR trim(linked_behavior_id) = '' THEN '[]'
22
+ ELSE json_array(linked_behavior_id)
23
+ END
24
+ WHERE linked_behavior_ids_json = '[]';
@@ -0,0 +1,14 @@
1
+ CREATE TABLE IF NOT EXISTS work_adjustments (
2
+ id TEXT PRIMARY KEY,
3
+ entity_type TEXT NOT NULL,
4
+ entity_id TEXT NOT NULL,
5
+ requested_delta_minutes INTEGER NOT NULL,
6
+ applied_delta_minutes INTEGER NOT NULL,
7
+ note TEXT NOT NULL DEFAULT '',
8
+ actor TEXT,
9
+ source TEXT NOT NULL,
10
+ created_at TEXT NOT NULL
11
+ );
12
+
13
+ CREATE INDEX IF NOT EXISTS idx_work_adjustments_entity
14
+ ON work_adjustments(entity_type, entity_id, created_at DESC);
@@ -0,0 +1,17 @@
1
+ CREATE TABLE IF NOT EXISTS weekly_review_closures (
2
+ id TEXT PRIMARY KEY,
3
+ week_key TEXT NOT NULL UNIQUE,
4
+ week_start_date TEXT NOT NULL,
5
+ week_end_date TEXT NOT NULL,
6
+ window_label TEXT NOT NULL,
7
+ actor TEXT,
8
+ source TEXT NOT NULL,
9
+ reward_id TEXT NOT NULL,
10
+ activity_event_id TEXT NOT NULL,
11
+ created_at TEXT NOT NULL,
12
+ FOREIGN KEY (reward_id) REFERENCES reward_ledger(id) ON DELETE RESTRICT,
13
+ FOREIGN KEY (activity_event_id) REFERENCES activity_events(id) ON DELETE RESTRICT
14
+ );
15
+
16
+ CREATE INDEX IF NOT EXISTS idx_weekly_review_closures_created_at
17
+ ON weekly_review_closures(created_at DESC);
@@ -0,0 +1,147 @@
1
+ ALTER TABLE projects ADD COLUMN scheduling_rules_json TEXT NOT NULL DEFAULT '{}';
2
+ ALTER TABLE tasks ADD COLUMN scheduling_rules_json TEXT;
3
+ ALTER TABLE tasks ADD COLUMN planned_duration_seconds INTEGER;
4
+ ALTER TABLE task_runs ADD COLUMN override_reason TEXT;
5
+
6
+ CREATE TABLE IF NOT EXISTS stored_secrets (
7
+ id TEXT PRIMARY KEY,
8
+ cipher_text TEXT NOT NULL,
9
+ description TEXT NOT NULL DEFAULT '',
10
+ created_at TEXT NOT NULL,
11
+ updated_at TEXT NOT NULL
12
+ );
13
+
14
+ CREATE TABLE IF NOT EXISTS calendar_connections (
15
+ id TEXT PRIMARY KEY,
16
+ provider TEXT NOT NULL,
17
+ label TEXT NOT NULL,
18
+ account_label TEXT NOT NULL DEFAULT '',
19
+ status TEXT NOT NULL DEFAULT 'connected',
20
+ config_json TEXT NOT NULL DEFAULT '{}',
21
+ credentials_secret_id TEXT NOT NULL,
22
+ forge_calendar_id TEXT,
23
+ last_synced_at TEXT,
24
+ last_sync_error TEXT,
25
+ created_at TEXT NOT NULL,
26
+ updated_at TEXT NOT NULL,
27
+ FOREIGN KEY (credentials_secret_id) REFERENCES stored_secrets(id) ON DELETE RESTRICT,
28
+ FOREIGN KEY (forge_calendar_id) REFERENCES calendar_calendars(id) ON DELETE SET NULL
29
+ );
30
+
31
+ CREATE TABLE IF NOT EXISTS calendar_calendars (
32
+ id TEXT PRIMARY KEY,
33
+ connection_id TEXT NOT NULL,
34
+ remote_id TEXT NOT NULL,
35
+ title TEXT NOT NULL,
36
+ description TEXT NOT NULL DEFAULT '',
37
+ color TEXT NOT NULL DEFAULT '#7dd3fc',
38
+ timezone TEXT NOT NULL DEFAULT 'UTC',
39
+ is_primary INTEGER NOT NULL DEFAULT 0,
40
+ can_write INTEGER NOT NULL DEFAULT 1,
41
+ forge_managed INTEGER NOT NULL DEFAULT 0,
42
+ sync_cursor TEXT,
43
+ remote_etag TEXT,
44
+ last_synced_at TEXT,
45
+ created_at TEXT NOT NULL,
46
+ updated_at TEXT NOT NULL,
47
+ UNIQUE(connection_id, remote_id),
48
+ FOREIGN KEY (connection_id) REFERENCES calendar_connections(id) ON DELETE CASCADE
49
+ );
50
+
51
+ CREATE TABLE IF NOT EXISTS calendar_events (
52
+ id TEXT PRIMARY KEY,
53
+ connection_id TEXT NOT NULL,
54
+ calendar_id TEXT NOT NULL,
55
+ remote_id TEXT NOT NULL,
56
+ remote_href TEXT,
57
+ remote_etag TEXT,
58
+ ownership TEXT NOT NULL DEFAULT 'external',
59
+ status TEXT NOT NULL DEFAULT 'confirmed',
60
+ title TEXT NOT NULL,
61
+ description TEXT NOT NULL DEFAULT '',
62
+ location TEXT NOT NULL DEFAULT '',
63
+ start_at TEXT NOT NULL,
64
+ end_at TEXT NOT NULL,
65
+ is_all_day INTEGER NOT NULL DEFAULT 0,
66
+ availability TEXT NOT NULL DEFAULT 'busy',
67
+ event_type TEXT NOT NULL DEFAULT '',
68
+ categories_json TEXT NOT NULL DEFAULT '[]',
69
+ raw_payload_json TEXT NOT NULL DEFAULT '{}',
70
+ remote_updated_at TEXT,
71
+ deleted_at TEXT,
72
+ created_at TEXT NOT NULL,
73
+ updated_at TEXT NOT NULL,
74
+ UNIQUE(connection_id, calendar_id, remote_id),
75
+ FOREIGN KEY (connection_id) REFERENCES calendar_connections(id) ON DELETE CASCADE,
76
+ FOREIGN KEY (calendar_id) REFERENCES calendar_calendars(id) ON DELETE CASCADE
77
+ );
78
+
79
+ CREATE INDEX IF NOT EXISTS idx_calendar_events_calendar_start
80
+ ON calendar_events(calendar_id, start_at, end_at);
81
+
82
+ CREATE INDEX IF NOT EXISTS idx_calendar_events_connection_updated
83
+ ON calendar_events(connection_id, updated_at);
84
+
85
+ CREATE TABLE IF NOT EXISTS work_block_templates (
86
+ id TEXT PRIMARY KEY,
87
+ title TEXT NOT NULL,
88
+ kind TEXT NOT NULL,
89
+ color TEXT NOT NULL DEFAULT '#60a5fa',
90
+ timezone TEXT NOT NULL DEFAULT 'UTC',
91
+ weekdays_json TEXT NOT NULL DEFAULT '[]',
92
+ start_minute INTEGER NOT NULL,
93
+ end_minute INTEGER NOT NULL,
94
+ blocking_state TEXT NOT NULL DEFAULT 'blocked',
95
+ created_at TEXT NOT NULL,
96
+ updated_at TEXT NOT NULL
97
+ );
98
+
99
+ CREATE TABLE IF NOT EXISTS work_block_instances (
100
+ id TEXT PRIMARY KEY,
101
+ template_id TEXT NOT NULL,
102
+ date_key TEXT NOT NULL,
103
+ start_at TEXT NOT NULL,
104
+ end_at TEXT NOT NULL,
105
+ title TEXT NOT NULL,
106
+ kind TEXT NOT NULL,
107
+ color TEXT NOT NULL DEFAULT '#60a5fa',
108
+ blocking_state TEXT NOT NULL DEFAULT 'blocked',
109
+ calendar_event_id TEXT,
110
+ created_at TEXT NOT NULL,
111
+ updated_at TEXT NOT NULL,
112
+ UNIQUE(template_id, date_key, start_at, end_at),
113
+ FOREIGN KEY (template_id) REFERENCES work_block_templates(id) ON DELETE CASCADE,
114
+ FOREIGN KEY (calendar_event_id) REFERENCES calendar_events(id) ON DELETE SET NULL
115
+ );
116
+
117
+ CREATE INDEX IF NOT EXISTS idx_work_block_instances_date
118
+ ON work_block_instances(date_key, start_at, end_at);
119
+
120
+ CREATE TABLE IF NOT EXISTS task_timeboxes (
121
+ id TEXT PRIMARY KEY,
122
+ task_id TEXT NOT NULL,
123
+ project_id TEXT,
124
+ connection_id TEXT,
125
+ calendar_id TEXT,
126
+ remote_event_id TEXT,
127
+ linked_task_run_id TEXT,
128
+ status TEXT NOT NULL DEFAULT 'planned',
129
+ source TEXT NOT NULL DEFAULT 'manual',
130
+ title TEXT NOT NULL,
131
+ starts_at TEXT NOT NULL,
132
+ ends_at TEXT NOT NULL,
133
+ override_reason TEXT,
134
+ created_at TEXT NOT NULL,
135
+ updated_at TEXT NOT NULL,
136
+ FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE,
137
+ FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET NULL,
138
+ FOREIGN KEY (connection_id) REFERENCES calendar_connections(id) ON DELETE SET NULL,
139
+ FOREIGN KEY (calendar_id) REFERENCES calendar_calendars(id) ON DELETE SET NULL,
140
+ FOREIGN KEY (linked_task_run_id) REFERENCES task_runs(id) ON DELETE SET NULL
141
+ );
142
+
143
+ CREATE INDEX IF NOT EXISTS idx_task_timeboxes_task_start
144
+ ON task_timeboxes(task_id, starts_at, ends_at);
145
+
146
+ CREATE INDEX IF NOT EXISTS idx_task_timeboxes_run
147
+ ON task_timeboxes(linked_task_run_id);
@@ -0,0 +1,195 @@
1
+ CREATE TABLE IF NOT EXISTS forge_events (
2
+ id TEXT PRIMARY KEY,
3
+ preferred_connection_id TEXT,
4
+ preferred_calendar_id TEXT,
5
+ ownership TEXT NOT NULL DEFAULT 'forge',
6
+ origin_type TEXT NOT NULL DEFAULT 'native',
7
+ status TEXT NOT NULL DEFAULT 'confirmed',
8
+ title TEXT NOT NULL,
9
+ description TEXT NOT NULL DEFAULT '',
10
+ location TEXT NOT NULL DEFAULT '',
11
+ start_at TEXT NOT NULL,
12
+ end_at TEXT NOT NULL,
13
+ timezone TEXT NOT NULL DEFAULT 'UTC',
14
+ is_all_day INTEGER NOT NULL DEFAULT 0,
15
+ availability TEXT NOT NULL DEFAULT 'busy',
16
+ event_type TEXT NOT NULL DEFAULT '',
17
+ categories_json TEXT NOT NULL DEFAULT '[]',
18
+ deleted_at TEXT,
19
+ created_at TEXT NOT NULL,
20
+ updated_at TEXT NOT NULL,
21
+ FOREIGN KEY (preferred_connection_id) REFERENCES calendar_connections(id) ON DELETE SET NULL,
22
+ FOREIGN KEY (preferred_calendar_id) REFERENCES calendar_calendars(id) ON DELETE SET NULL
23
+ );
24
+
25
+ CREATE INDEX IF NOT EXISTS idx_forge_events_time
26
+ ON forge_events(start_at, end_at);
27
+
28
+ CREATE INDEX IF NOT EXISTS idx_forge_events_calendar
29
+ ON forge_events(preferred_calendar_id, start_at, end_at);
30
+
31
+ CREATE TABLE IF NOT EXISTS forge_event_sources (
32
+ id TEXT PRIMARY KEY,
33
+ forge_event_id TEXT NOT NULL,
34
+ provider TEXT NOT NULL,
35
+ connection_id TEXT,
36
+ calendar_id TEXT,
37
+ remote_calendar_id TEXT,
38
+ remote_event_id TEXT NOT NULL,
39
+ remote_uid TEXT,
40
+ recurrence_instance_id TEXT,
41
+ is_master_recurring INTEGER NOT NULL DEFAULT 0,
42
+ remote_href TEXT,
43
+ remote_etag TEXT,
44
+ sync_state TEXT NOT NULL DEFAULT 'synced',
45
+ raw_payload_json TEXT NOT NULL DEFAULT '{}',
46
+ last_synced_at TEXT,
47
+ created_at TEXT NOT NULL,
48
+ updated_at TEXT NOT NULL,
49
+ FOREIGN KEY (forge_event_id) REFERENCES forge_events(id) ON DELETE CASCADE,
50
+ FOREIGN KEY (connection_id) REFERENCES calendar_connections(id) ON DELETE SET NULL,
51
+ FOREIGN KEY (calendar_id) REFERENCES calendar_calendars(id) ON DELETE SET NULL,
52
+ UNIQUE(provider, connection_id, calendar_id, remote_event_id)
53
+ );
54
+
55
+ CREATE INDEX IF NOT EXISTS idx_forge_event_sources_event
56
+ ON forge_event_sources(forge_event_id);
57
+
58
+ CREATE INDEX IF NOT EXISTS idx_forge_event_sources_remote
59
+ ON forge_event_sources(connection_id, calendar_id, remote_event_id);
60
+
61
+ CREATE TABLE IF NOT EXISTS forge_event_links (
62
+ id TEXT PRIMARY KEY,
63
+ forge_event_id TEXT NOT NULL,
64
+ entity_type TEXT NOT NULL,
65
+ entity_id TEXT NOT NULL,
66
+ relationship_type TEXT NOT NULL DEFAULT 'context',
67
+ created_at TEXT NOT NULL,
68
+ updated_at TEXT NOT NULL,
69
+ FOREIGN KEY (forge_event_id) REFERENCES forge_events(id) ON DELETE CASCADE,
70
+ UNIQUE(forge_event_id, entity_type, entity_id, relationship_type)
71
+ );
72
+
73
+ CREATE INDEX IF NOT EXISTS idx_forge_event_links_entity
74
+ ON forge_event_links(entity_type, entity_id);
75
+
76
+ CREATE TABLE IF NOT EXISTS forge_event_metadata (
77
+ id TEXT PRIMARY KEY,
78
+ forge_event_id TEXT NOT NULL,
79
+ namespace TEXT NOT NULL,
80
+ key TEXT NOT NULL,
81
+ value_json TEXT NOT NULL DEFAULT 'null',
82
+ created_at TEXT NOT NULL,
83
+ updated_at TEXT NOT NULL,
84
+ FOREIGN KEY (forge_event_id) REFERENCES forge_events(id) ON DELETE CASCADE,
85
+ UNIQUE(forge_event_id, namespace, key)
86
+ );
87
+
88
+ ALTER TABLE task_timeboxes ADD COLUMN forge_event_id TEXT REFERENCES forge_events(id) ON DELETE SET NULL;
89
+
90
+ INSERT INTO forge_events (
91
+ id,
92
+ preferred_connection_id,
93
+ preferred_calendar_id,
94
+ ownership,
95
+ origin_type,
96
+ status,
97
+ title,
98
+ description,
99
+ location,
100
+ start_at,
101
+ end_at,
102
+ timezone,
103
+ is_all_day,
104
+ availability,
105
+ event_type,
106
+ categories_json,
107
+ deleted_at,
108
+ created_at,
109
+ updated_at
110
+ )
111
+ SELECT
112
+ calendar_events.id,
113
+ calendar_events.connection_id,
114
+ calendar_events.calendar_id,
115
+ calendar_events.ownership,
116
+ calendar_connections.provider,
117
+ calendar_events.status,
118
+ calendar_events.title,
119
+ calendar_events.description,
120
+ calendar_events.location,
121
+ calendar_events.start_at,
122
+ calendar_events.end_at,
123
+ COALESCE(calendar_calendars.timezone, 'UTC'),
124
+ calendar_events.is_all_day,
125
+ calendar_events.availability,
126
+ calendar_events.event_type,
127
+ calendar_events.categories_json,
128
+ calendar_events.deleted_at,
129
+ calendar_events.created_at,
130
+ calendar_events.updated_at
131
+ FROM calendar_events
132
+ LEFT JOIN calendar_connections
133
+ ON calendar_connections.id = calendar_events.connection_id
134
+ LEFT JOIN calendar_calendars
135
+ ON calendar_calendars.id = calendar_events.calendar_id
136
+ WHERE NOT EXISTS (
137
+ SELECT 1 FROM forge_events WHERE forge_events.id = calendar_events.id
138
+ );
139
+
140
+ INSERT INTO forge_event_sources (
141
+ id,
142
+ forge_event_id,
143
+ provider,
144
+ connection_id,
145
+ calendar_id,
146
+ remote_calendar_id,
147
+ remote_event_id,
148
+ remote_uid,
149
+ recurrence_instance_id,
150
+ is_master_recurring,
151
+ remote_href,
152
+ remote_etag,
153
+ sync_state,
154
+ raw_payload_json,
155
+ last_synced_at,
156
+ created_at,
157
+ updated_at
158
+ )
159
+ SELECT
160
+ 'evsrc_' || lower(hex(randomblob(5))),
161
+ calendar_events.id,
162
+ calendar_connections.provider,
163
+ calendar_events.connection_id,
164
+ calendar_events.calendar_id,
165
+ calendar_calendars.remote_id,
166
+ calendar_events.remote_id,
167
+ json_extract(calendar_events.raw_payload_json, '$.uid'),
168
+ json_extract(calendar_events.raw_payload_json, '$.recurrenceid'),
169
+ CASE
170
+ WHEN json_extract(calendar_events.raw_payload_json, '$.rrule') IS NOT NULL THEN 1
171
+ ELSE 0
172
+ END,
173
+ calendar_events.remote_href,
174
+ calendar_events.remote_etag,
175
+ CASE
176
+ WHEN calendar_events.deleted_at IS NOT NULL THEN 'deleted'
177
+ ELSE 'synced'
178
+ END,
179
+ calendar_events.raw_payload_json,
180
+ COALESCE(calendar_events.remote_updated_at, calendar_events.updated_at),
181
+ calendar_events.created_at,
182
+ calendar_events.updated_at
183
+ FROM calendar_events
184
+ LEFT JOIN calendar_connections
185
+ ON calendar_connections.id = calendar_events.connection_id
186
+ LEFT JOIN calendar_calendars
187
+ ON calendar_calendars.id = calendar_events.calendar_id
188
+ WHERE NOT EXISTS (
189
+ SELECT 1
190
+ FROM forge_event_sources
191
+ WHERE forge_event_sources.forge_event_id = calendar_events.id
192
+ AND forge_event_sources.connection_id = calendar_events.connection_id
193
+ AND forge_event_sources.calendar_id = calendar_events.calendar_id
194
+ AND forge_event_sources.remote_event_id = calendar_events.remote_id
195
+ );
@@ -0,0 +1,6 @@
1
+ ALTER TABLE calendar_calendars
2
+ ADD COLUMN selected_for_sync INTEGER NOT NULL DEFAULT 1;
3
+
4
+ UPDATE calendar_calendars
5
+ SET selected_for_sync = 1
6
+ WHERE selected_for_sync IS NULL;
@@ -0,0 +1,11 @@
1
+ UPDATE calendar_calendars
2
+ SET timezone = 'UTC'
3
+ WHERE TRIM(COALESCE(timezone, '')) = '';
4
+
5
+ UPDATE forge_events
6
+ SET timezone = 'UTC'
7
+ WHERE TRIM(COALESCE(timezone, '')) = '';
8
+
9
+ UPDATE work_block_templates
10
+ SET timezone = 'UTC'
11
+ WHERE TRIM(COALESCE(timezone, '')) = '';
@@ -0,0 +1,7 @@
1
+ ALTER TABLE work_block_templates ADD COLUMN starts_on TEXT;
2
+ ALTER TABLE work_block_templates ADD COLUMN ends_on TEXT;
3
+
4
+ CREATE INDEX IF NOT EXISTS idx_work_block_templates_active_window
5
+ ON work_block_templates(starts_on, ends_on, start_minute);
6
+
7
+ DROP TABLE IF EXISTS work_block_instances;
@@ -0,0 +1,8 @@
1
+ ALTER TABLE app_settings
2
+ ADD COLUMN microsoft_client_id TEXT NOT NULL DEFAULT '';
3
+
4
+ ALTER TABLE app_settings
5
+ ADD COLUMN microsoft_tenant_id TEXT NOT NULL DEFAULT 'common';
6
+
7
+ ALTER TABLE app_settings
8
+ ADD COLUMN microsoft_redirect_uri TEXT NOT NULL DEFAULT '';
@@ -0,0 +1,8 @@
1
+ ALTER TABLE notes
2
+ ADD COLUMN tags_json TEXT NOT NULL DEFAULT '[]';
3
+
4
+ ALTER TABLE notes
5
+ ADD COLUMN destroy_at TEXT;
6
+
7
+ CREATE INDEX IF NOT EXISTS idx_notes_destroy_at
8
+ ON notes(destroy_at);