forge-openclaw-plugin 0.2.25 → 0.2.27

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 (237) hide show
  1. package/README.md +59 -3
  2. package/dist/assets/{board-VmF4FAfr.js → board-C6jCchjI.js} +3 -3
  3. package/dist/assets/{board-VmF4FAfr.js.map → board-C6jCchjI.js.map} +1 -1
  4. package/dist/assets/index-DVvS8iiU.css +1 -0
  5. package/dist/assets/index-zYB-9Dfo.js +85 -0
  6. package/dist/assets/index-zYB-9Dfo.js.map +1 -0
  7. package/dist/assets/knowledge-graph-layout.worker-DRvzPxhP.js +2 -0
  8. package/dist/assets/knowledge-graph-layout.worker-DRvzPxhP.js.map +1 -0
  9. package/dist/assets/{motion-DvkU14p-.js → motion-DFHrH2rd.js} +2 -2
  10. package/dist/assets/{motion-DvkU14p-.js.map → motion-DFHrH2rd.js.map} +1 -1
  11. package/dist/assets/{table-DgiPof9E.js → table-ZL7Di_u3.js} +2 -2
  12. package/dist/assets/{table-DgiPof9E.js.map → table-ZL7Di_u3.js.map} +1 -1
  13. package/dist/assets/{ui-nYfoC0Gq.js → ui-CKNPpz7q.js} +2 -2
  14. package/dist/assets/{ui-nYfoC0Gq.js.map → ui-CKNPpz7q.js.map} +1 -1
  15. package/dist/assets/vendor-DoNZuFhn.js +1247 -0
  16. package/dist/assets/vendor-DoNZuFhn.js.map +1 -0
  17. package/dist/index.html +7 -8
  18. package/dist/openclaw/local-runtime.d.ts +3 -1
  19. package/dist/openclaw/local-runtime.js +67 -15
  20. package/dist/openclaw/plugin-entry-shared.js +24 -2
  21. package/dist/openclaw/plugin-sdk-types.d.ts +17 -0
  22. package/dist/openclaw/routes.d.ts +27 -0
  23. package/dist/openclaw/routes.js +16 -12
  24. package/dist/openclaw/tools.js +0 -3
  25. package/dist/server/server/migrations/001_core.sql +411 -0
  26. package/dist/server/server/migrations/002_psyche.sql +392 -0
  27. package/dist/server/server/migrations/003_habits.sql +30 -0
  28. package/dist/server/server/migrations/004_habit_links.sql +8 -0
  29. package/dist/server/server/migrations/005_habit_psyche_links.sql +24 -0
  30. package/dist/server/server/migrations/006_work_adjustments.sql +14 -0
  31. package/dist/server/server/migrations/007_weekly_review_closures.sql +17 -0
  32. package/dist/server/server/migrations/008_calendar_execution.sql +147 -0
  33. package/dist/server/server/migrations/009_true_calendar_events.sql +195 -0
  34. package/dist/server/server/migrations/010_calendar_selection_state.sql +6 -0
  35. package/dist/server/server/migrations/011_calendar_timezone_backfill.sql +11 -0
  36. package/dist/server/server/migrations/012_work_block_ranges.sql +7 -0
  37. package/dist/server/server/migrations/013_microsoft_local_auth_settings.sql +8 -0
  38. package/dist/server/server/migrations/014_note_tags_and_ephemeral.sql +8 -0
  39. package/dist/server/server/migrations/015_multi_user_and_strategies.sql +244 -0
  40. package/dist/server/server/migrations/016_health_companion.sql +158 -0
  41. package/dist/server/server/migrations/016_strategy_contracts_and_user_graph.sql +22 -0
  42. package/dist/server/server/migrations/017_preferences.sql +131 -0
  43. package/dist/server/server/migrations/018_preference_catalogs.sql +31 -0
  44. package/dist/server/server/migrations/019_wiki_memory.sql +255 -0
  45. package/dist/server/server/migrations/020_wiki_page_hierarchy.sql +11 -0
  46. package/dist/server/server/migrations/021_hide_evidence_from_wiki_index.sql +3 -0
  47. package/dist/server/server/migrations/022_wiki_ingest_background.sql +85 -0
  48. package/dist/server/server/migrations/023_diagnostic_logs.sql +28 -0
  49. package/dist/server/server/migrations/024_questionnaires.sql +96 -0
  50. package/dist/server/server/migrations/025_ai_model_connections.sql +26 -0
  51. package/dist/server/server/migrations/026_custom_theme_settings.sql +2 -0
  52. package/dist/server/server/migrations/027_ai_processors.sql +31 -0
  53. package/dist/server/server/migrations/028_movement_domain.sql +136 -0
  54. package/dist/server/server/migrations/029_watch_micro_capture.sql +23 -0
  55. package/dist/server/server/migrations/030_surface_layouts.sql +5 -0
  56. package/dist/server/server/migrations/031_ai_processor_runtime_upgrades.sql +10 -0
  57. package/dist/server/server/migrations/032_ai_connectors.sql +44 -0
  58. package/dist/server/server/migrations/033_movement_trip_point_sync.sql +36 -0
  59. package/dist/server/server/migrations/034_movement_segment_sync.sql +49 -0
  60. package/dist/server/server/migrations/035_google_local_auth_settings.sql +2 -0
  61. package/dist/server/server/migrations/036_google_local_auth_client_secret.sql +2 -0
  62. package/dist/server/server/migrations/037_workbench_public_inputs_and_run_inputs.sql +5 -0
  63. package/dist/server/server/migrations/038_data_management_settings.sql +11 -0
  64. package/dist/server/server/migrations/039_life_force_and_action_points.sql +114 -0
  65. package/dist/server/server/migrations/040_screen_time_domain.sql +89 -0
  66. package/dist/server/server/migrations/041_companion_source_states.sql +21 -0
  67. package/dist/server/server/migrations/042_movement_boxes.sql +47 -0
  68. package/dist/server/server/migrations/043_movement_box_overlap_overrides.sql +26 -0
  69. package/dist/server/{app.js → server/src/app.js} +2112 -414
  70. package/dist/server/server/src/connectors/box-registry.js +223 -0
  71. package/dist/server/server/src/data-management-types.js +107 -0
  72. package/dist/server/{db.js → server/src/db.js} +72 -4
  73. package/dist/server/server/src/debug.js +19 -0
  74. package/dist/server/{demo-data.js → server/src/demo-data.js} +2 -2
  75. package/dist/server/{health.js → server/src/health.js} +702 -18
  76. package/dist/server/{managers → server/src/managers}/platform/llm-manager.js +7 -4
  77. package/dist/server/server/src/managers/platform/mock-workbench-provider.js +149 -0
  78. package/dist/server/{managers → server/src/managers}/platform/secrets-manager.js +18 -1
  79. package/dist/server/{managers → server/src/managers}/runtime.js +9 -0
  80. package/dist/server/{movement.js → server/src/movement.js} +1971 -112
  81. package/dist/server/{openapi.js → server/src/openapi.js} +491 -3
  82. package/dist/server/{psyche-types.js → server/src/psyche-types.js} +9 -1
  83. package/dist/server/{repositories → server/src/repositories}/activity-events.js +8 -0
  84. package/dist/server/{repositories → server/src/repositories}/ai-connectors.js +758 -47
  85. package/dist/server/{repositories → server/src/repositories}/calendar.js +1 -1
  86. package/dist/server/{repositories → server/src/repositories}/habits.js +37 -1
  87. package/dist/server/{repositories → server/src/repositories}/model-settings.js +13 -3
  88. package/dist/server/{repositories → server/src/repositories}/notes.js +3 -0
  89. package/dist/server/{repositories → server/src/repositories}/settings.js +431 -21
  90. package/dist/server/{repositories → server/src/repositories}/tasks.js +170 -10
  91. package/dist/server/server/src/runtime-data-root.js +82 -0
  92. package/dist/server/server/src/screen-time.js +802 -0
  93. package/dist/server/{services → server/src/services}/calendar-runtime.js +775 -58
  94. package/dist/server/server/src/services/data-management.js +788 -0
  95. package/dist/server/{services → server/src/services}/entity-crud.js +205 -2
  96. package/dist/server/server/src/services/google-calendar-oauth-config.js +176 -0
  97. package/dist/server/server/src/services/knowledge-graph.js +1455 -0
  98. package/dist/server/server/src/services/life-force-model.js +197 -0
  99. package/dist/server/server/src/services/life-force.js +1270 -0
  100. package/dist/server/server/src/services/psyche-observation-calendar.js +413 -0
  101. package/dist/server/{types.js → server/src/types.js} +420 -29
  102. package/dist/server/server/src/web.js +332 -0
  103. package/dist/server/src/components/customization/utility-widgets.js +439 -0
  104. package/dist/server/src/components/ui/info-tooltip.js +25 -0
  105. package/dist/server/src/components/workbench-boxes/calendar/calendar-boxes.js +78 -0
  106. package/dist/server/src/components/workbench-boxes/goals/goals-boxes.js +62 -0
  107. package/dist/server/src/components/workbench-boxes/habits/habits-boxes.js +62 -0
  108. package/dist/server/src/components/workbench-boxes/health/health-boxes.js +147 -0
  109. package/dist/server/src/components/workbench-boxes/insights/insights-boxes.js +50 -0
  110. package/dist/server/src/components/workbench-boxes/kanban/kanban-boxes.js +136 -0
  111. package/dist/server/src/components/workbench-boxes/movement/movement-boxes.js +47 -0
  112. package/dist/server/src/components/workbench-boxes/notes/notes-boxes.js +132 -0
  113. package/dist/server/src/components/workbench-boxes/overview/overview-boxes.js +65 -0
  114. package/dist/server/src/components/workbench-boxes/preferences/preferences-boxes.js +78 -0
  115. package/dist/server/src/components/workbench-boxes/projects/projects-boxes.js +62 -0
  116. package/dist/server/src/components/workbench-boxes/psyche/psyche-boxes.js +88 -0
  117. package/dist/server/src/components/workbench-boxes/questionnaires/questionnaires-boxes.js +61 -0
  118. package/dist/server/src/components/workbench-boxes/review/review-boxes.js +53 -0
  119. package/dist/server/src/components/workbench-boxes/shared/define-workbench-box.js +6 -0
  120. package/dist/server/src/components/workbench-boxes/shared/generic-node-view.js +49 -0
  121. package/dist/server/src/components/workbench-boxes/strategies/strategies-boxes.js +62 -0
  122. package/dist/server/src/components/workbench-boxes/tasks/tasks-boxes.js +76 -0
  123. package/dist/server/src/components/workbench-boxes/today/today-boxes.js +78 -0
  124. package/dist/server/src/components/workbench-boxes/wiki/wiki-boxes.js +60 -0
  125. package/dist/server/src/lib/api-error.js +37 -0
  126. package/dist/server/src/lib/api.js +2118 -0
  127. package/dist/server/src/lib/calendar-name-deduper.js +144 -0
  128. package/dist/server/src/lib/data-management-types.js +1 -0
  129. package/dist/server/src/lib/diagnostics.js +67 -0
  130. package/dist/server/src/lib/entity-visuals.js +279 -0
  131. package/dist/server/src/lib/knowledge-graph-types.js +276 -0
  132. package/dist/server/src/lib/knowledge-graph.js +470 -0
  133. package/dist/server/src/lib/psyche-types.js +1 -0
  134. package/dist/server/src/lib/questionnaire-types.js +1 -0
  135. package/dist/server/src/lib/runtime-paths.js +24 -0
  136. package/dist/server/src/lib/schemas.js +238 -0
  137. package/dist/server/src/lib/snapshot-normalizer.js +416 -0
  138. package/dist/server/src/lib/theme-system.js +319 -0
  139. package/dist/server/src/lib/types.js +1 -0
  140. package/dist/server/src/lib/utils.js +22 -0
  141. package/dist/server/src/lib/workbench/boxes.js +16 -0
  142. package/dist/server/src/lib/workbench/contracts.js +229 -0
  143. package/dist/server/src/lib/workbench/nodes.js +215 -0
  144. package/dist/server/src/lib/workbench/registry.js +120 -0
  145. package/dist/server/src/lib/workbench/runtime.js +397 -0
  146. package/dist/server/src/lib/workbench/tool-catalog.js +68 -0
  147. package/openclaw.plugin.json +1 -1
  148. package/package.json +1 -1
  149. package/server/index.js +68 -0
  150. package/server/migrations/035_google_local_auth_settings.sql +2 -0
  151. package/server/migrations/036_google_local_auth_client_secret.sql +2 -0
  152. package/server/migrations/037_workbench_public_inputs_and_run_inputs.sql +5 -0
  153. package/server/migrations/038_data_management_settings.sql +11 -0
  154. package/server/migrations/039_life_force_and_action_points.sql +114 -0
  155. package/server/migrations/040_screen_time_domain.sql +89 -0
  156. package/server/migrations/041_companion_source_states.sql +21 -0
  157. package/server/migrations/042_movement_boxes.sql +47 -0
  158. package/server/migrations/043_movement_box_overlap_overrides.sql +26 -0
  159. package/skills/forge-openclaw/SKILL.md +27 -11
  160. package/skills/forge-openclaw/entity_conversation_playbooks.md +411 -46
  161. package/skills/forge-openclaw/psyche_entity_playbooks.md +195 -20
  162. package/dist/assets/index-CFCKDIMH.js +0 -67
  163. package/dist/assets/index-CFCKDIMH.js.map +0 -1
  164. package/dist/assets/index-ZPY6U1TU.css +0 -1
  165. package/dist/assets/vendor-D9PTEPSB.js +0 -824
  166. package/dist/assets/vendor-D9PTEPSB.js.map +0 -1
  167. package/dist/assets/viz-Cqb6s--o.js +0 -34
  168. package/dist/assets/viz-Cqb6s--o.js.map +0 -1
  169. package/dist/server/connectors/box-registry.js +0 -257
  170. package/dist/server/services/psyche-observation-calendar.js +0 -46
  171. package/dist/server/web.js +0 -98
  172. /package/dist/server/{discovery-advertiser.js → server/src/discovery-advertiser.js} +0 -0
  173. /package/dist/server/{e2e-server.js → server/src/e2e-server.js} +0 -0
  174. /package/dist/server/{errors.js → server/src/errors.js} +0 -0
  175. /package/dist/server/{index.js → server/src/index.js} +0 -0
  176. /package/dist/server/{managers → server/src/managers}/base.js +0 -0
  177. /package/dist/server/{managers → server/src/managers}/contracts.js +0 -0
  178. /package/dist/server/{managers → server/src/managers}/platform/api-gateway-manager.js +0 -0
  179. /package/dist/server/{managers → server/src/managers}/platform/audit-manager.js +0 -0
  180. /package/dist/server/{managers → server/src/managers}/platform/authentication-manager.js +0 -0
  181. /package/dist/server/{managers → server/src/managers}/platform/authorization-manager.js +0 -0
  182. /package/dist/server/{managers → server/src/managers}/platform/background-job-manager.js +0 -0
  183. /package/dist/server/{managers → server/src/managers}/platform/configuration-manager.js +0 -0
  184. /package/dist/server/{managers → server/src/managers}/platform/database-manager.js +0 -0
  185. /package/dist/server/{managers → server/src/managers}/platform/event-bus-manager.js +0 -0
  186. /package/dist/server/{managers → server/src/managers}/platform/external-service-manager.js +0 -0
  187. /package/dist/server/{managers → server/src/managers}/platform/health-manager.js +0 -0
  188. /package/dist/server/{managers → server/src/managers}/platform/migration-manager.js +0 -0
  189. /package/dist/server/{managers → server/src/managers}/platform/openai-responses-provider.js +0 -0
  190. /package/dist/server/{managers → server/src/managers}/platform/search-index-manager.js +0 -0
  191. /package/dist/server/{managers → server/src/managers}/platform/session-manager.js +0 -0
  192. /package/dist/server/{managers → server/src/managers}/platform/storage-manager.js +0 -0
  193. /package/dist/server/{managers → server/src/managers}/platform/token-manager.js +0 -0
  194. /package/dist/server/{managers → server/src/managers}/platform/transaction-manager.js +0 -0
  195. /package/dist/server/{managers → server/src/managers}/platform/trusted-network.js +0 -0
  196. /package/dist/server/{managers → server/src/managers}/type-guards.js +0 -0
  197. /package/dist/server/{preferences-seeds.js → server/src/preferences-seeds.js} +0 -0
  198. /package/dist/server/{preferences-types.js → server/src/preferences-types.js} +0 -0
  199. /package/dist/server/{questionnaire-flow.js → server/src/questionnaire-flow.js} +0 -0
  200. /package/dist/server/{questionnaire-seeds.js → server/src/questionnaire-seeds.js} +0 -0
  201. /package/dist/server/{questionnaire-types.js → server/src/questionnaire-types.js} +0 -0
  202. /package/dist/server/{repositories → server/src/repositories}/ai-processors.js +0 -0
  203. /package/dist/server/{repositories → server/src/repositories}/collaboration.js +0 -0
  204. /package/dist/server/{repositories → server/src/repositories}/deleted-entities.js +0 -0
  205. /package/dist/server/{repositories → server/src/repositories}/diagnostic-logs.js +0 -0
  206. /package/dist/server/{repositories → server/src/repositories}/domains.js +0 -0
  207. /package/dist/server/{repositories → server/src/repositories}/entity-ownership.js +0 -0
  208. /package/dist/server/{repositories → server/src/repositories}/event-log.js +0 -0
  209. /package/dist/server/{repositories → server/src/repositories}/goals.js +0 -0
  210. /package/dist/server/{repositories → server/src/repositories}/preferences.js +0 -0
  211. /package/dist/server/{repositories → server/src/repositories}/projects.js +0 -0
  212. /package/dist/server/{repositories → server/src/repositories}/psyche.js +0 -0
  213. /package/dist/server/{repositories → server/src/repositories}/questionnaires.js +0 -0
  214. /package/dist/server/{repositories → server/src/repositories}/rewards.js +0 -0
  215. /package/dist/server/{repositories → server/src/repositories}/strategies.js +0 -0
  216. /package/dist/server/{repositories → server/src/repositories}/surface-layouts.js +0 -0
  217. /package/dist/server/{repositories → server/src/repositories}/tags.js +0 -0
  218. /package/dist/server/{repositories → server/src/repositories}/task-runs.js +0 -0
  219. /package/dist/server/{repositories → server/src/repositories}/users.js +0 -0
  220. /package/dist/server/{repositories → server/src/repositories}/weekly-reviews.js +0 -0
  221. /package/dist/server/{repositories → server/src/repositories}/wiki-memory.js +0 -0
  222. /package/dist/server/{repositories → server/src/repositories}/work-adjustments.js +0 -0
  223. /package/dist/server/{seed-demo.js → server/src/seed-demo.js} +0 -0
  224. /package/dist/server/{services → server/src/services}/context.js +0 -0
  225. /package/dist/server/{services → server/src/services}/dashboard.js +0 -0
  226. /package/dist/server/{services → server/src/services}/gamification.js +0 -0
  227. /package/dist/server/{services → server/src/services}/insights.js +0 -0
  228. /package/dist/server/{services → server/src/services}/openai-codex-oauth.js +0 -0
  229. /package/dist/server/{services → server/src/services}/projects.js +0 -0
  230. /package/dist/server/{services → server/src/services}/psyche.js +0 -0
  231. /package/dist/server/{services → server/src/services}/relations.js +0 -0
  232. /package/dist/server/{services → server/src/services}/reviews.js +0 -0
  233. /package/dist/server/{services → server/src/services}/run-recovery.js +0 -0
  234. /package/dist/server/{services → server/src/services}/tagging.js +0 -0
  235. /package/dist/server/{services → server/src/services}/task-run-watchdog.js +0 -0
  236. /package/dist/server/{services → server/src/services}/work-time.js +0 -0
  237. /package/dist/server/{watch-mobile.js → server/src/watch-mobile.js} +0 -0
@@ -1,9 +1,23 @@
1
1
  import { createHash, randomBytes, randomUUID } from "node:crypto";
2
- import { getDatabase, runInTransaction } from "../db.js";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import path from "node:path";
4
+ import { getDatabase, getEffectiveDataRoot, runInTransaction } from "../db.js";
5
+ import { logForgeDebug } from "../debug.js";
3
6
  import { recordActivityEvent } from "./activity-events.js";
4
7
  import { recordEventLog } from "./event-log.js";
8
+ import { resolveGoogleCalendarOauthPublicConfig } from "../services/google-calendar-oauth-config.js";
5
9
  import { buildConnectionAgentIdentity, FORGE_DEFAULT_AGENT_ID, listAiModelConnections, syncForgeManagedWikiProfile } from "./model-settings.js";
6
10
  import { createAgentTokenSchema, agentIdentitySchema, customThemeSchema, settingsPayloadSchema, updateSettingsSchema } from "../types.js";
11
+ const settingsFileSchema = settingsPayloadSchema.deepPartial();
12
+ let settingsFileSyncDepth = 0;
13
+ let lastSettingsFileStatus = {
14
+ path: path.join(getEffectiveDataRoot(), "forge.json"),
15
+ exists: false,
16
+ valid: false,
17
+ syncState: "uninitialized",
18
+ parseError: null,
19
+ overrideKeys: []
20
+ };
7
21
  function boolFromInt(value) {
8
22
  return value === 1;
9
23
  }
@@ -23,7 +37,15 @@ function normalizeMicrosoftTenantId(value) {
23
37
  }
24
38
  function normalizeMicrosoftRedirectUri(value) {
25
39
  const trimmed = value?.trim();
26
- return trimmed && trimmed.length > 0 ? trimmed : defaultMicrosoftRedirectUri();
40
+ return trimmed && trimmed.length > 0
41
+ ? trimmed
42
+ : defaultMicrosoftRedirectUri();
43
+ }
44
+ function logCalendarSettingsDebug(message, details) {
45
+ const serialized = Object.entries(details)
46
+ .map(([key, value]) => `${key}=${JSON.stringify(value)}`)
47
+ .join(" ");
48
+ logForgeDebug(`[forge-calendar-settings] ${message} ${serialized}`);
27
49
  }
28
50
  function normalizeModelConnectionId(value) {
29
51
  const trimmed = value?.trim();
@@ -44,6 +66,237 @@ function parseCustomThemeJson(raw) {
44
66
  return null;
45
67
  }
46
68
  }
69
+ function getForgeSettingsFilePath() {
70
+ return path.join(getEffectiveDataRoot(), "forge.json");
71
+ }
72
+ function writeForgeSettingsFileSnapshot(payload) {
73
+ const filePath = getForgeSettingsFilePath();
74
+ mkdirSync(path.dirname(filePath), { recursive: true });
75
+ writeFileSync(filePath, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
76
+ lastSettingsFileStatus = {
77
+ path: filePath,
78
+ exists: true,
79
+ valid: true,
80
+ syncState: "mirrored_from_database",
81
+ parseError: null,
82
+ overrideKeys: []
83
+ };
84
+ }
85
+ function readForgeSettingsFile() {
86
+ const filePath = getForgeSettingsFilePath();
87
+ if (!existsSync(filePath)) {
88
+ return {
89
+ filePath,
90
+ exists: false,
91
+ valid: false,
92
+ settings: null,
93
+ parseError: null
94
+ };
95
+ }
96
+ try {
97
+ const raw = readFileSync(filePath, "utf8");
98
+ const parsed = JSON.parse(raw);
99
+ const settings = settingsFileSchema.parse(parsed);
100
+ return {
101
+ filePath,
102
+ exists: true,
103
+ valid: true,
104
+ settings,
105
+ parseError: null
106
+ };
107
+ }
108
+ catch (error) {
109
+ return {
110
+ filePath,
111
+ exists: true,
112
+ valid: false,
113
+ settings: null,
114
+ parseError: error instanceof Error ? error.message : String(error)
115
+ };
116
+ }
117
+ }
118
+ function toSettingsFileOverrideInput(input) {
119
+ const next = {};
120
+ if (input.profile) {
121
+ next.profile = {};
122
+ if (input.profile.operatorName !== undefined) {
123
+ next.profile.operatorName = input.profile.operatorName;
124
+ }
125
+ if (input.profile.operatorEmail !== undefined) {
126
+ next.profile.operatorEmail = input.profile.operatorEmail;
127
+ }
128
+ if (input.profile.operatorTitle !== undefined) {
129
+ next.profile.operatorTitle = input.profile.operatorTitle;
130
+ }
131
+ if (Object.keys(next.profile).length === 0) {
132
+ delete next.profile;
133
+ }
134
+ }
135
+ if (input.notifications) {
136
+ next.notifications = {};
137
+ if (input.notifications.goalDriftAlerts !== undefined) {
138
+ next.notifications.goalDriftAlerts = input.notifications.goalDriftAlerts;
139
+ }
140
+ if (input.notifications.dailyQuestReminders !== undefined) {
141
+ next.notifications.dailyQuestReminders =
142
+ input.notifications.dailyQuestReminders;
143
+ }
144
+ if (input.notifications.achievementCelebrations !== undefined) {
145
+ next.notifications.achievementCelebrations =
146
+ input.notifications.achievementCelebrations;
147
+ }
148
+ if (Object.keys(next.notifications).length === 0) {
149
+ delete next.notifications;
150
+ }
151
+ }
152
+ if (input.execution) {
153
+ next.execution = {};
154
+ if (input.execution.maxActiveTasks !== undefined) {
155
+ next.execution.maxActiveTasks = input.execution.maxActiveTasks;
156
+ }
157
+ if (input.execution.timeAccountingMode !== undefined) {
158
+ next.execution.timeAccountingMode = input.execution.timeAccountingMode;
159
+ }
160
+ if (Object.keys(next.execution).length === 0) {
161
+ delete next.execution;
162
+ }
163
+ }
164
+ if (input.themePreference !== undefined) {
165
+ next.themePreference = input.themePreference;
166
+ }
167
+ if (input.customTheme !== undefined) {
168
+ next.customTheme = input.customTheme;
169
+ }
170
+ if (input.localePreference !== undefined) {
171
+ next.localePreference = input.localePreference;
172
+ }
173
+ if (input.security?.psycheAuthRequired !== undefined) {
174
+ next.security = {
175
+ psycheAuthRequired: input.security.psycheAuthRequired
176
+ };
177
+ }
178
+ if (input.calendarProviders) {
179
+ next.calendarProviders = {};
180
+ if (input.calendarProviders.google) {
181
+ next.calendarProviders.google = {};
182
+ if (input.calendarProviders.google.clientId !== undefined) {
183
+ next.calendarProviders.google.clientId =
184
+ input.calendarProviders.google.clientId;
185
+ }
186
+ if (input.calendarProviders.google.clientSecret !== undefined) {
187
+ next.calendarProviders.google.clientSecret =
188
+ input.calendarProviders.google.clientSecret;
189
+ }
190
+ if (Object.keys(next.calendarProviders.google).length === 0) {
191
+ delete next.calendarProviders.google;
192
+ }
193
+ }
194
+ if (input.calendarProviders.microsoft) {
195
+ next.calendarProviders.microsoft = {};
196
+ if (input.calendarProviders.microsoft.clientId !== undefined) {
197
+ next.calendarProviders.microsoft.clientId =
198
+ input.calendarProviders.microsoft.clientId;
199
+ }
200
+ if (input.calendarProviders.microsoft.tenantId !== undefined) {
201
+ next.calendarProviders.microsoft.tenantId =
202
+ input.calendarProviders.microsoft.tenantId;
203
+ }
204
+ if (input.calendarProviders.microsoft.redirectUri !== undefined) {
205
+ next.calendarProviders.microsoft.redirectUri =
206
+ input.calendarProviders.microsoft.redirectUri;
207
+ }
208
+ if (Object.keys(next.calendarProviders.microsoft).length === 0) {
209
+ delete next.calendarProviders.microsoft;
210
+ }
211
+ }
212
+ if (Object.keys(next.calendarProviders).length === 0) {
213
+ delete next.calendarProviders;
214
+ }
215
+ }
216
+ if (input.modelSettings?.forgeAgent) {
217
+ next.modelSettings = {
218
+ forgeAgent: {}
219
+ };
220
+ if (input.modelSettings.forgeAgent.basicChat) {
221
+ next.modelSettings.forgeAgent.basicChat = {};
222
+ if (input.modelSettings.forgeAgent.basicChat.connectionId !== undefined) {
223
+ next.modelSettings.forgeAgent.basicChat.connectionId =
224
+ input.modelSettings.forgeAgent.basicChat.connectionId;
225
+ }
226
+ if (input.modelSettings.forgeAgent.basicChat.model !== undefined) {
227
+ next.modelSettings.forgeAgent.basicChat.model =
228
+ input.modelSettings.forgeAgent.basicChat.model;
229
+ }
230
+ if (Object.keys(next.modelSettings.forgeAgent.basicChat).length === 0) {
231
+ delete next.modelSettings.forgeAgent.basicChat;
232
+ }
233
+ }
234
+ if (input.modelSettings.forgeAgent.wiki) {
235
+ next.modelSettings.forgeAgent.wiki = {};
236
+ if (input.modelSettings.forgeAgent.wiki.connectionId !== undefined) {
237
+ next.modelSettings.forgeAgent.wiki.connectionId =
238
+ input.modelSettings.forgeAgent.wiki.connectionId;
239
+ }
240
+ if (input.modelSettings.forgeAgent.wiki.model !== undefined) {
241
+ next.modelSettings.forgeAgent.wiki.model =
242
+ input.modelSettings.forgeAgent.wiki.model;
243
+ }
244
+ if (Object.keys(next.modelSettings.forgeAgent.wiki).length === 0) {
245
+ delete next.modelSettings.forgeAgent.wiki;
246
+ }
247
+ }
248
+ if (Object.keys(next.modelSettings.forgeAgent).length === 0) {
249
+ delete next.modelSettings;
250
+ }
251
+ }
252
+ return next;
253
+ }
254
+ function listOverrideKeys(input) {
255
+ const keys = [];
256
+ const pushNestedKeys = (prefix, value) => {
257
+ for (const [key, nestedValue] of Object.entries(value)) {
258
+ if (nestedValue &&
259
+ typeof nestedValue === "object" &&
260
+ !Array.isArray(nestedValue)) {
261
+ pushNestedKeys(`${prefix}.${key}`, nestedValue);
262
+ }
263
+ else if (nestedValue !== undefined) {
264
+ keys.push(`${prefix}.${key}`);
265
+ }
266
+ }
267
+ };
268
+ for (const [key, value] of Object.entries(input)) {
269
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
270
+ keys.push(key);
271
+ continue;
272
+ }
273
+ pushNestedKeys(key, value);
274
+ }
275
+ return keys.sort();
276
+ }
277
+ function pickComparableOverrideSubset(source, template) {
278
+ const picked = {};
279
+ for (const [key, templateValue] of Object.entries(template)) {
280
+ if (templateValue === undefined) {
281
+ continue;
282
+ }
283
+ const sourceValue = source[key];
284
+ if (templateValue &&
285
+ typeof templateValue === "object" &&
286
+ !Array.isArray(templateValue) &&
287
+ sourceValue &&
288
+ typeof sourceValue === "object" &&
289
+ !Array.isArray(sourceValue)) {
290
+ const nested = pickComparableOverrideSubset(sourceValue, templateValue);
291
+ if (Object.keys(nested).length > 0) {
292
+ picked[key] = nested;
293
+ }
294
+ continue;
295
+ }
296
+ picked[key] = sourceValue;
297
+ }
298
+ return picked;
299
+ }
47
300
  function mapAgent(row) {
48
301
  return agentIdentitySchema.parse({
49
302
  id: row.id,
@@ -137,7 +390,7 @@ function readSettingsRow() {
137
390
  .prepare(`SELECT
138
391
  operator_name, operator_email, operator_title, theme_preference, custom_theme_json, locale_preference,
139
392
  goal_drift_alerts, daily_quest_reminders, achievement_celebrations, max_active_tasks, time_accounting_mode,
140
- integrity_score, last_audit_at, psyche_auth_required, microsoft_client_id, microsoft_tenant_id, microsoft_redirect_uri,
393
+ integrity_score, last_audit_at, psyche_auth_required, google_client_id, google_client_secret, microsoft_client_id, microsoft_tenant_id, microsoft_redirect_uri,
141
394
  forge_basic_chat_connection_id, forge_basic_chat_model, forge_wiki_connection_id, forge_wiki_model, created_at, updated_at
142
395
  FROM app_settings
143
396
  WHERE id = 1`)
@@ -210,9 +463,21 @@ export function isPsycheAuthRequired() {
210
463
  .get();
211
464
  return row ? boolFromInt(row.psyche_auth_required) : false;
212
465
  }
213
- export function getSettings() {
466
+ function buildSettingsPayloadFromDatabase() {
214
467
  const row = readSettingsRow();
215
468
  const connections = listAiModelConnections();
469
+ const googleConfig = resolveGoogleCalendarOauthPublicConfig(process.env, {
470
+ clientId: row.google_client_id,
471
+ clientSecret: row.google_client_secret
472
+ });
473
+ logCalendarSettingsDebug("get_settings", {
474
+ storedGoogleClientId: row.google_client_id,
475
+ storedGoogleClientSecret: row.google_client_secret.length > 0,
476
+ resolvedGoogleClientId: googleConfig.clientId,
477
+ resolvedGoogleClientSecret: googleConfig.clientSecret.length > 0,
478
+ googleIsConfigured: googleConfig.isConfigured,
479
+ googleRedirectUri: googleConfig.redirectUri
480
+ });
216
481
  const microsoftClientId = row.microsoft_client_id?.trim() ?? "";
217
482
  const microsoftTenantId = normalizeMicrosoftTenantId(row.microsoft_tenant_id);
218
483
  const microsoftRedirectUri = normalizeMicrosoftRedirectUri(row.microsoft_redirect_uri);
@@ -244,10 +509,12 @@ export function getSettings() {
244
509
  lastAuditAt: row.last_audit_at,
245
510
  storageMode: "local-first",
246
511
  activeSessions: 1,
247
- tokenCount: listAgentTokens().filter((token) => token.status === "active").length,
512
+ tokenCount: listAgentTokens().filter((token) => token.status === "active")
513
+ .length,
248
514
  psycheAuthRequired: boolFromInt(row.psyche_auth_required)
249
515
  },
250
516
  calendarProviders: {
517
+ google: googleConfig,
251
518
  microsoft: {
252
519
  clientId: microsoftClientId,
253
520
  tenantId: microsoftTenantId,
@@ -269,14 +536,18 @@ export function getSettings() {
269
536
  connectionLabel: basicChatConnection?.label ?? null,
270
537
  provider: basicChatConnection?.provider ?? null,
271
538
  baseUrl: basicChatConnection?.baseUrl ?? null,
272
- model: row.forge_basic_chat_model?.trim() || basicChatConnection?.model || "gpt-5.4-mini"
539
+ model: row.forge_basic_chat_model?.trim() ||
540
+ basicChatConnection?.model ||
541
+ "gpt-5.4-mini"
273
542
  },
274
543
  wiki: {
275
544
  connectionId: wikiConnection?.id ?? null,
276
545
  connectionLabel: wikiConnection?.label ?? null,
277
546
  provider: wikiConnection?.provider ?? null,
278
547
  baseUrl: wikiConnection?.baseUrl ?? null,
279
- model: row.forge_wiki_model?.trim() || wikiConnection?.model || "gpt-5.4-mini"
548
+ model: row.forge_wiki_model?.trim() ||
549
+ wikiConnection?.model ||
550
+ "gpt-5.4-mini"
280
551
  }
281
552
  },
282
553
  connections,
@@ -292,11 +563,114 @@ export function getSettings() {
292
563
  agentTokens: listAgentTokens()
293
564
  });
294
565
  }
295
- export function updateSettings(input, options = {}) {
566
+ function reconcileSettingsFileWithDatabase(current) {
567
+ const fileState = readForgeSettingsFile();
568
+ if (!fileState.exists) {
569
+ writeForgeSettingsFileSnapshot(current);
570
+ lastSettingsFileStatus = {
571
+ path: fileState.filePath,
572
+ exists: true,
573
+ valid: true,
574
+ syncState: "created_from_database",
575
+ parseError: null,
576
+ overrideKeys: []
577
+ };
578
+ return current;
579
+ }
580
+ if (!fileState.valid || !fileState.settings) {
581
+ lastSettingsFileStatus = {
582
+ path: fileState.filePath,
583
+ exists: true,
584
+ valid: false,
585
+ syncState: "invalid",
586
+ parseError: fileState.parseError,
587
+ overrideKeys: []
588
+ };
589
+ return current;
590
+ }
591
+ const overrideInput = toSettingsFileOverrideInput(fileState.settings);
592
+ const overrideKeys = listOverrideKeys(overrideInput);
593
+ let next = current;
594
+ const currentOverride = pickComparableOverrideSubset(toSettingsFileOverrideInput(current), overrideInput);
595
+ const overridesDiffer = JSON.stringify(currentOverride) !== JSON.stringify(overrideInput);
596
+ if (overrideKeys.length > 0 && overridesDiffer) {
597
+ next = updateSettingsInternal(overrideInput, {
598
+ mirrorSettingsFile: false
599
+ });
600
+ }
601
+ const serialized = `${JSON.stringify(next, null, 2)}\n`;
602
+ let syncState = overrideKeys.length > 0 && overridesDiffer
603
+ ? "applied_file_overrides"
604
+ : "up_to_date";
605
+ try {
606
+ const existing = readFileSync(fileState.filePath, "utf8");
607
+ if (existing !== serialized) {
608
+ mkdirSync(path.dirname(fileState.filePath), { recursive: true });
609
+ writeFileSync(fileState.filePath, serialized, "utf8");
610
+ if (syncState !== "applied_file_overrides") {
611
+ syncState = "mirrored_from_database";
612
+ }
613
+ }
614
+ }
615
+ catch {
616
+ mkdirSync(path.dirname(fileState.filePath), { recursive: true });
617
+ writeFileSync(fileState.filePath, serialized, "utf8");
618
+ if (syncState !== "applied_file_overrides") {
619
+ syncState = "mirrored_from_database";
620
+ }
621
+ }
622
+ lastSettingsFileStatus = {
623
+ path: fileState.filePath,
624
+ exists: true,
625
+ valid: true,
626
+ syncState,
627
+ parseError: null,
628
+ overrideKeys
629
+ };
630
+ return next;
631
+ }
632
+ export function getSettingsFileStatus() {
633
+ return {
634
+ ...lastSettingsFileStatus,
635
+ path: getForgeSettingsFilePath()
636
+ };
637
+ }
638
+ export function mirrorSettingsFileFromCurrentState() {
639
+ const current = buildSettingsPayloadFromDatabase();
640
+ writeForgeSettingsFileSnapshot(current);
641
+ return current;
642
+ }
643
+ export function getSettings() {
644
+ if (settingsFileSyncDepth > 0) {
645
+ return buildSettingsPayloadFromDatabase();
646
+ }
647
+ settingsFileSyncDepth += 1;
648
+ try {
649
+ return reconcileSettingsFileWithDatabase(buildSettingsPayloadFromDatabase());
650
+ }
651
+ finally {
652
+ settingsFileSyncDepth = Math.max(0, settingsFileSyncDepth - 1);
653
+ }
654
+ }
655
+ function updateSettingsInternal(input, options = {}) {
296
656
  const parsed = updateSettingsSchema.parse(input);
297
657
  return runInTransaction(() => {
298
- const current = getSettings();
658
+ const current = buildSettingsPayloadFromDatabase();
299
659
  const now = new Date().toISOString();
660
+ const nextGoogleClientId = parsed.calendarProviders?.google?.clientId?.trim() ??
661
+ current.calendarProviders.google.storedClientId;
662
+ const nextGoogleClientSecret = parsed.calendarProviders?.google?.clientSecret?.trim() ??
663
+ current.calendarProviders.google.storedClientSecret;
664
+ logCalendarSettingsDebug("update_settings_requested", {
665
+ requestedGoogleClientId: parsed.calendarProviders?.google?.clientId ?? null,
666
+ requestedGoogleClientSecret: parsed.calendarProviders?.google?.clientSecret !== undefined
667
+ ? parsed.calendarProviders.google.clientSecret.length > 0
668
+ : null,
669
+ currentGoogleClientId: current.calendarProviders.google.storedClientId,
670
+ currentGoogleClientSecret: current.calendarProviders.google.storedClientSecret.length > 0,
671
+ nextGoogleClientId,
672
+ nextGoogleClientSecret: nextGoogleClientSecret.length > 0
673
+ });
300
674
  const next = {
301
675
  profile: {
302
676
  operatorName: parsed.profile?.operatorName ?? current.profile.operatorName,
@@ -304,19 +678,30 @@ export function updateSettings(input, options = {}) {
304
678
  operatorTitle: parsed.profile?.operatorTitle ?? current.profile.operatorTitle
305
679
  },
306
680
  notifications: {
307
- goalDriftAlerts: parsed.notifications?.goalDriftAlerts ?? current.notifications.goalDriftAlerts,
308
- dailyQuestReminders: parsed.notifications?.dailyQuestReminders ?? current.notifications.dailyQuestReminders,
309
- achievementCelebrations: parsed.notifications?.achievementCelebrations ?? current.notifications.achievementCelebrations
681
+ goalDriftAlerts: parsed.notifications?.goalDriftAlerts ??
682
+ current.notifications.goalDriftAlerts,
683
+ dailyQuestReminders: parsed.notifications?.dailyQuestReminders ??
684
+ current.notifications.dailyQuestReminders,
685
+ achievementCelebrations: parsed.notifications?.achievementCelebrations ??
686
+ current.notifications.achievementCelebrations
310
687
  },
311
688
  execution: {
312
689
  maxActiveTasks: parsed.execution?.maxActiveTasks ?? current.execution.maxActiveTasks,
313
- timeAccountingMode: parsed.execution?.timeAccountingMode ?? current.execution.timeAccountingMode
690
+ timeAccountingMode: parsed.execution?.timeAccountingMode ??
691
+ current.execution.timeAccountingMode
314
692
  },
315
693
  themePreference: parsed.themePreference ?? current.themePreference,
316
- customTheme: parsed.customTheme === undefined ? (current.customTheme ?? null) : parsed.customTheme,
694
+ customTheme: parsed.customTheme === undefined
695
+ ? (current.customTheme ?? null)
696
+ : parsed.customTheme,
317
697
  localePreference: parsed.localePreference ?? current.localePreference,
318
- psycheAuthRequired: parsed.security?.psycheAuthRequired ?? current.security.psycheAuthRequired,
698
+ psycheAuthRequired: parsed.security?.psycheAuthRequired ??
699
+ current.security.psycheAuthRequired,
319
700
  calendarProviders: {
701
+ google: resolveGoogleCalendarOauthPublicConfig(process.env, {
702
+ clientId: nextGoogleClientId,
703
+ clientSecret: nextGoogleClientSecret
704
+ }),
320
705
  microsoft: {
321
706
  clientId: parsed.calendarProviders?.microsoft?.clientId?.trim() ??
322
707
  current.calendarProviders.microsoft.clientId,
@@ -332,14 +717,15 @@ export function updateSettings(input, options = {}) {
332
717
  connectionId: parsed.modelSettings?.forgeAgent?.basicChat?.connectionId !==
333
718
  undefined
334
719
  ? normalizeModelConnectionId(parsed.modelSettings.forgeAgent.basicChat.connectionId)
335
- : current.modelSettings.forgeAgent.basicChat.connectionId ?? "",
720
+ : (current.modelSettings.forgeAgent.basicChat.connectionId ??
721
+ ""),
336
722
  model: parsed.modelSettings?.forgeAgent?.basicChat?.model?.trim() ||
337
723
  current.modelSettings.forgeAgent.basicChat.model
338
724
  },
339
725
  wiki: {
340
726
  connectionId: parsed.modelSettings?.forgeAgent?.wiki?.connectionId !== undefined
341
727
  ? normalizeModelConnectionId(parsed.modelSettings.forgeAgent.wiki.connectionId)
342
- : current.modelSettings.forgeAgent.wiki.connectionId ?? "",
728
+ : (current.modelSettings.forgeAgent.wiki.connectionId ?? ""),
343
729
  model: parsed.modelSettings?.forgeAgent?.wiki?.model?.trim() ||
344
730
  current.modelSettings.forgeAgent.wiki.model
345
731
  }
@@ -350,10 +736,16 @@ export function updateSettings(input, options = {}) {
350
736
  .prepare(`UPDATE app_settings
351
737
  SET operator_name = ?, operator_email = ?, operator_title = ?, theme_preference = ?, custom_theme_json = ?, locale_preference = ?,
352
738
  goal_drift_alerts = ?, daily_quest_reminders = ?, achievement_celebrations = ?, max_active_tasks = ?, time_accounting_mode = ?,
353
- psyche_auth_required = ?, microsoft_client_id = ?, microsoft_tenant_id = ?, microsoft_redirect_uri = ?,
739
+ psyche_auth_required = ?, google_client_id = ?, google_client_secret = ?, microsoft_client_id = ?, microsoft_tenant_id = ?, microsoft_redirect_uri = ?,
354
740
  forge_basic_chat_connection_id = ?, forge_basic_chat_model = ?, forge_wiki_connection_id = ?, forge_wiki_model = ?, updated_at = ?
355
741
  WHERE id = 1`)
356
- .run(next.profile.operatorName, next.profile.operatorEmail, next.profile.operatorTitle, next.themePreference, next.customTheme ? JSON.stringify(next.customTheme) : "", next.localePreference, toInt(next.notifications.goalDriftAlerts), toInt(next.notifications.dailyQuestReminders), toInt(next.notifications.achievementCelebrations), next.execution.maxActiveTasks, next.execution.timeAccountingMode, toInt(next.psycheAuthRequired), next.calendarProviders.microsoft.clientId, next.calendarProviders.microsoft.tenantId, next.calendarProviders.microsoft.redirectUri, next.modelSettings.forgeAgent.basicChat.connectionId, next.modelSettings.forgeAgent.basicChat.model, next.modelSettings.forgeAgent.wiki.connectionId, next.modelSettings.forgeAgent.wiki.model, now);
742
+ .run(next.profile.operatorName, next.profile.operatorEmail, next.profile.operatorTitle, next.themePreference, next.customTheme ? JSON.stringify(next.customTheme) : "", next.localePreference, toInt(next.notifications.goalDriftAlerts), toInt(next.notifications.dailyQuestReminders), toInt(next.notifications.achievementCelebrations), next.execution.maxActiveTasks, next.execution.timeAccountingMode, toInt(next.psycheAuthRequired), nextGoogleClientId, nextGoogleClientSecret, next.calendarProviders.microsoft.clientId, next.calendarProviders.microsoft.tenantId, next.calendarProviders.microsoft.redirectUri, next.modelSettings.forgeAgent.basicChat.connectionId, next.modelSettings.forgeAgent.basicChat.model, next.modelSettings.forgeAgent.wiki.connectionId, next.modelSettings.forgeAgent.wiki.model, now);
743
+ logCalendarSettingsDebug("update_settings_committed", {
744
+ persistedGoogleClientId: nextGoogleClientId,
745
+ persistedGoogleClientSecret: nextGoogleClientSecret.length > 0,
746
+ persistedMicrosoftClientId: next.calendarProviders.microsoft.clientId,
747
+ updatedAt: now
748
+ });
357
749
  if (options.secrets) {
358
750
  syncForgeManagedWikiProfile(options.secrets);
359
751
  }
@@ -374,6 +766,9 @@ export function updateSettings(input, options = {}) {
374
766
  dailyQuestReminders: next.notifications.dailyQuestReminders,
375
767
  maxActiveTasks: next.execution.maxActiveTasks,
376
768
  timeAccountingMode: next.execution.timeAccountingMode,
769
+ googleConfigured: next.calendarProviders.google.isConfigured,
770
+ googleAppBaseUrl: next.calendarProviders.google.appBaseUrl,
771
+ googleRedirectUri: next.calendarProviders.google.redirectUri,
377
772
  microsoftConfigured: next.calendarProviders.microsoft.clientId.trim().length > 0,
378
773
  microsoftTenantId: next.calendarProviders.microsoft.tenantId,
379
774
  forgeBasicChatModel: next.modelSettings.forgeAgent.basicChat.model,
@@ -383,7 +778,17 @@ export function updateSettings(input, options = {}) {
383
778
  }
384
779
  });
385
780
  }
386
- return getSettings();
781
+ const updated = buildSettingsPayloadFromDatabase();
782
+ if (options.mirrorSettingsFile !== false) {
783
+ writeForgeSettingsFileSnapshot(updated);
784
+ }
785
+ return updated;
786
+ });
787
+ }
788
+ export function updateSettings(input, options = {}) {
789
+ return updateSettingsInternal(input, {
790
+ ...options,
791
+ mirrorSettingsFile: true
387
792
  });
388
793
  }
389
794
  export function createAgentToken(input, activity) {
@@ -429,6 +834,7 @@ export function createAgentToken(input, activity) {
429
834
  }
430
835
  });
431
836
  }
837
+ mirrorSettingsFileFromCurrentState();
432
838
  return {
433
839
  token,
434
840
  tokenSummary
@@ -466,6 +872,7 @@ export function rotateAgentToken(tokenId, activity) {
466
872
  source: activity.source
467
873
  });
468
874
  }
875
+ mirrorSettingsFileFromCurrentState();
469
876
  return {
470
877
  token,
471
878
  tokenSummary
@@ -501,6 +908,7 @@ export function revokeAgentToken(tokenId, activity) {
501
908
  source: activity.source
502
909
  });
503
910
  }
911
+ mirrorSettingsFileFromCurrentState();
504
912
  return tokenSummary;
505
913
  });
506
914
  }
@@ -532,6 +940,8 @@ export function verifyAgentToken(token) {
532
940
  if (!row || row.revoked_at) {
533
941
  return null;
534
942
  }
535
- getDatabase().prepare(`UPDATE agent_tokens SET last_used_at = ?, updated_at = ? WHERE id = ?`).run(new Date().toISOString(), new Date().toISOString(), row.id);
943
+ getDatabase()
944
+ .prepare(`UPDATE agent_tokens SET last_used_at = ?, updated_at = ? WHERE id = ?`)
945
+ .run(new Date().toISOString(), new Date().toISOString(), row.id);
536
946
  return mapToken(row);
537
947
  }