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
@@ -0,0 +1,223 @@
1
+ import { getDatabase } from "../db.js";
2
+ import { getFitnessViewData, getSleepViewData } from "../health.js";
3
+ import { listMovementPlaces } from "../movement.js";
4
+ import { getInsightsPayload } from "../services/insights.js";
5
+ import { getWeeklyReviewPayload } from "../services/reviews.js";
6
+ import { createNote, listNotes } from "../repositories/notes.js";
7
+ import { updateTask } from "../repositories/tasks.js";
8
+ import { getOverviewContext } from "../services/context.js";
9
+ import { searchEntities } from "../services/entity-crud.js";
10
+ import { getWikiHealth, listWikiPages } from "../repositories/wiki-memory.js";
11
+ import { executeCommonWorkbenchTool, mapWorkbenchTools } from "../../../src/lib/workbench/runtime.js";
12
+ import { getWorkbenchNodeCatalog, getWorkbenchNodeDefinition } from "../../../src/lib/workbench/registry.js";
13
+ import { normalizeWorkbenchPortDefinition } from "../../../src/lib/workbench/nodes.js";
14
+ function createSnapshotForConnectorOutput(boxId) {
15
+ const outputId = boxId.replace(/^connector-output:/, "");
16
+ const rows = getDatabase()
17
+ .prepare(`SELECT id, title, published_outputs_json, last_run_json FROM ai_connectors ORDER BY updated_at DESC`)
18
+ .all();
19
+ for (const row of rows) {
20
+ const outputs = JSON.parse(row.published_outputs_json || "[]");
21
+ const output = outputs.find((entry) => entry.id === outputId);
22
+ if (!output) {
23
+ continue;
24
+ }
25
+ const lastRun = row.last_run_json
26
+ ? JSON.parse(row.last_run_json)
27
+ : null;
28
+ const published = lastRun?.result?.outputs?.[outputId] ?? null;
29
+ return {
30
+ boxId,
31
+ label: output.label,
32
+ capturedAt: new Date().toISOString(),
33
+ contentText: published?.text ?? `${row.title}\nNo published output has been generated yet.`,
34
+ contentJson: published?.json ?? null,
35
+ tools: []
36
+ };
37
+ }
38
+ return null;
39
+ }
40
+ function createRuntimeContext(input) {
41
+ const services = {
42
+ entities: {
43
+ search: searchEntities
44
+ },
45
+ notes: {
46
+ create: ((input) => createNote(input, {
47
+ source: "agent",
48
+ actor: "Workbench"
49
+ })),
50
+ list: listNotes
51
+ },
52
+ movement: {
53
+ listPlaces: listMovementPlaces
54
+ },
55
+ health: {
56
+ getSleepViewData: getSleepViewData,
57
+ getFitnessViewData: getFitnessViewData
58
+ },
59
+ overview: {
60
+ getContext: (() => getOverviewContext()),
61
+ getWeeklyReview: (() => getWeeklyReviewPayload()),
62
+ getInsights: (() => getInsightsPayload())
63
+ },
64
+ wiki: {
65
+ listPages: ((input) => listWikiPages({
66
+ spaceId: typeof input?.spaceId === "string" ? input.spaceId : undefined,
67
+ kind: typeof input?.kind === "string" ? input.kind : undefined,
68
+ limit: typeof input?.limit === "number" ? input.limit : undefined
69
+ })),
70
+ getHealth: (() => getWikiHealth())
71
+ },
72
+ tasks: {
73
+ update: ((taskId, patch) => updateTask(taskId, patch, { source: "agent", actor: "Workbench" }))
74
+ }
75
+ };
76
+ return {
77
+ actor: input?.actor ?? { userIds: null, source: "api" },
78
+ services,
79
+ routeParams: input?.routeParams,
80
+ filters: input?.filters,
81
+ now: new Date().toISOString()
82
+ };
83
+ }
84
+ function toCatalogEntry(definition) {
85
+ if (!definition) {
86
+ return null;
87
+ }
88
+ const toPortDefinition = (port) => normalizeWorkbenchPortDefinition({
89
+ key: port.key,
90
+ label: port.label,
91
+ kind: port.kind,
92
+ description: "description" in port ? port.description : undefined,
93
+ required: port.required ?? false,
94
+ expandableKeys: "expandableKeys" in port ? (port.expandableKeys ?? []) : [],
95
+ modelName: "modelName" in port ? port.modelName : undefined,
96
+ itemKind: "itemKind" in port ? port.itemKind : undefined,
97
+ shape: "shape" in port
98
+ ? (port.shape ?? []).map((field) => ({
99
+ ...field,
100
+ required: field.required ?? false
101
+ }))
102
+ : [],
103
+ exampleValue: "exampleValue" in port ? port.exampleValue : undefined
104
+ });
105
+ return {
106
+ id: definition.id,
107
+ boxId: definition.id,
108
+ surfaceId: definition.surfaceId,
109
+ routePath: definition.routePath,
110
+ title: definition.title,
111
+ label: definition.title,
112
+ icon: definition.icon ?? null,
113
+ description: definition.description,
114
+ category: definition.category,
115
+ tags: definition.tags,
116
+ capabilityModes: [
117
+ "content",
118
+ ...(definition.tools.length > 0 ? ["tool"] : [])
119
+ ],
120
+ inputs: definition.inputs.map(toPortDefinition),
121
+ params: definition.params.map(toPortDefinition),
122
+ output: definition.output.map(toPortDefinition),
123
+ tools: definition.tools,
124
+ outputs: definition.output.map(toPortDefinition),
125
+ toolAdapters: definition.tools,
126
+ snapshotResolverKey: undefined
127
+ };
128
+ }
129
+ export function listForgeBoxCatalog() {
130
+ return getWorkbenchNodeCatalog();
131
+ }
132
+ export function getForgeBoxCatalogEntry(boxId) {
133
+ return toCatalogEntry(getWorkbenchNodeDefinition(boxId));
134
+ }
135
+ export function buildConnectorOutputCatalogEntry(input) {
136
+ return {
137
+ id: `connector-output:${input.outputId}`,
138
+ boxId: `connector-output:${input.outputId}`,
139
+ surfaceId: null,
140
+ routePath: `/workbench/${input.connectorId}`,
141
+ title: `${input.title} output`,
142
+ label: `${input.title} output`,
143
+ icon: null,
144
+ description: "Published Workbench output.",
145
+ category: "Workbench outputs",
146
+ tags: ["workbench", "output"],
147
+ capabilityModes: ["content"],
148
+ inputs: [],
149
+ params: [],
150
+ output: [
151
+ {
152
+ key: input.outputId,
153
+ label: "Published output",
154
+ kind: "record",
155
+ description: "Published output record exposed by this Workbench flow.",
156
+ required: false,
157
+ expandableKeys: [],
158
+ modelName: "WorkbenchPublishedOutput"
159
+ }
160
+ ],
161
+ tools: [],
162
+ outputs: [
163
+ {
164
+ key: input.outputId,
165
+ label: "Published output",
166
+ kind: "record",
167
+ description: "Published output record exposed by this Workbench flow.",
168
+ required: false,
169
+ expandableKeys: [],
170
+ modelName: "WorkbenchPublishedOutput"
171
+ }
172
+ ],
173
+ toolAdapters: []
174
+ };
175
+ }
176
+ export function resolveForgeBoxSnapshot(boxId, contextInput, executionInput) {
177
+ if (boxId.startsWith("connector-output:")) {
178
+ return (createSnapshotForConnectorOutput(boxId) ?? {
179
+ boxId,
180
+ label: boxId,
181
+ capturedAt: new Date().toISOString(),
182
+ contentText: "This connector output has not been generated yet.",
183
+ contentJson: null,
184
+ tools: []
185
+ });
186
+ }
187
+ const definition = getWorkbenchNodeDefinition(boxId);
188
+ if (!definition) {
189
+ return {
190
+ boxId,
191
+ label: boxId,
192
+ capturedAt: new Date().toISOString(),
193
+ contentText: "This Workbench node is not registered.",
194
+ contentJson: null,
195
+ tools: []
196
+ };
197
+ }
198
+ const execution = definition.execute({
199
+ nodeId: boxId,
200
+ definition,
201
+ inputs: executionInput?.inputs ?? {},
202
+ params: executionInput?.params ?? {},
203
+ context: createRuntimeContext(contextInput)
204
+ });
205
+ if (execution instanceof Promise) {
206
+ throw new Error("Workbench box execution must be synchronous for snapshot resolution.");
207
+ }
208
+ return {
209
+ boxId: definition.id,
210
+ label: definition.title,
211
+ capturedAt: new Date().toISOString(),
212
+ contentText: execution.primaryText,
213
+ contentJson: execution.payload,
214
+ tools: mapWorkbenchTools(definition.tools)
215
+ };
216
+ }
217
+ export function executeForgeBoxTool(boxId, toolKey, args, contextInput) {
218
+ const definition = getWorkbenchNodeDefinition(boxId);
219
+ if (!definition) {
220
+ throw new Error(`Unknown Forge box: ${boxId}`);
221
+ }
222
+ return executeCommonWorkbenchTool(createRuntimeContext(contextInput), definition, toolKey, args);
223
+ }
@@ -0,0 +1,107 @@
1
+ import { z } from "zod";
2
+ export const dataBackupModeSchema = z.enum([
3
+ "manual",
4
+ "automatic",
5
+ "pre_restore",
6
+ "pre_switch_root"
7
+ ]);
8
+ export const dataRootSwitchModeSchema = z.enum([
9
+ "migrate_current",
10
+ "adopt_existing"
11
+ ]);
12
+ export const dataExportFormatSchema = z.enum([
13
+ "sqlite",
14
+ "json",
15
+ "csv_bundle",
16
+ "schema_sql",
17
+ "schema_json"
18
+ ]);
19
+ export const dataLayoutSchema = z.enum(["flat", "legacy", "missing"]);
20
+ export const dataEntityCountSummarySchema = z.object({
21
+ notes: z.number().int().nonnegative(),
22
+ goals: z.number().int().nonnegative(),
23
+ projects: z.number().int().nonnegative(),
24
+ tasks: z.number().int().nonnegative(),
25
+ taskRuns: z.number().int().nonnegative(),
26
+ tags: z.number().int().nonnegative()
27
+ });
28
+ export const dataBackupEntrySchema = z.object({
29
+ id: z.string(),
30
+ createdAt: z.string(),
31
+ mode: dataBackupModeSchema,
32
+ note: z.string(),
33
+ sourceDataRoot: z.string(),
34
+ backupDirectory: z.string(),
35
+ archivePath: z.string(),
36
+ manifestPath: z.string(),
37
+ databasePath: z.string(),
38
+ sizeBytes: z.number().int().nonnegative(),
39
+ includesWiki: z.boolean(),
40
+ includesSecretsKey: z.boolean(),
41
+ counts: dataEntityCountSummarySchema
42
+ });
43
+ export const dataRuntimeSnapshotSchema = z.object({
44
+ dataRoot: z.string(),
45
+ databasePath: z.string(),
46
+ layout: dataLayoutSchema,
47
+ databaseSizeBytes: z.number().int().nonnegative(),
48
+ databaseLastModifiedAt: z.string().nullable(),
49
+ integrityOk: z.boolean(),
50
+ integrityMessage: z.string(),
51
+ counts: dataEntityCountSummarySchema
52
+ });
53
+ export const dataRecoveryCandidateSchema = z.object({
54
+ id: z.string(),
55
+ dataRoot: z.string(),
56
+ databasePath: z.string(),
57
+ layout: dataLayoutSchema,
58
+ sourceHint: z.string(),
59
+ databaseSizeBytes: z.number().int().nonnegative(),
60
+ databaseLastModifiedAt: z.string().nullable(),
61
+ integrityOk: z.boolean(),
62
+ integrityMessage: z.string(),
63
+ counts: dataEntityCountSummarySchema,
64
+ newerThanCurrent: z.boolean(),
65
+ sameAsCurrent: z.boolean()
66
+ });
67
+ export const dataExportOptionSchema = z.object({
68
+ format: dataExportFormatSchema,
69
+ label: z.string(),
70
+ description: z.string(),
71
+ mimeType: z.string(),
72
+ extension: z.string()
73
+ });
74
+ export const dataManagementSettingsSchema = z.object({
75
+ preferredDataRoot: z.string(),
76
+ backupDirectory: z.string(),
77
+ backupFrequencyHours: z.number().int().positive().nullable(),
78
+ autoRepairEnabled: z.boolean(),
79
+ lastAutoBackupAt: z.string().nullable(),
80
+ lastManualBackupAt: z.string().nullable()
81
+ });
82
+ export const dataManagementStateSchema = z.object({
83
+ generatedAt: z.string(),
84
+ current: dataRuntimeSnapshotSchema,
85
+ settings: dataManagementSettingsSchema,
86
+ backups: z.array(dataBackupEntrySchema),
87
+ exportOptions: z.array(dataExportOptionSchema)
88
+ });
89
+ export const updateDataManagementSettingsSchema = z.object({
90
+ backupDirectory: z.string().trim().optional(),
91
+ backupFrequencyHours: z.number().int().positive().nullable().optional(),
92
+ autoRepairEnabled: z.boolean().optional()
93
+ });
94
+ export const createDataBackupSchema = z.object({
95
+ note: z.string().trim().default("")
96
+ });
97
+ export const switchDataRootSchema = z.object({
98
+ targetDataRoot: z.string().trim().min(1),
99
+ mode: dataRootSwitchModeSchema.default("migrate_current"),
100
+ createSafetyBackup: z.boolean().default(true)
101
+ });
102
+ export const restoreDataBackupSchema = z.object({
103
+ createSafetyBackup: z.boolean().default(true)
104
+ });
105
+ export const dataExportQuerySchema = z.object({
106
+ format: dataExportFormatSchema
107
+ });
@@ -1,9 +1,11 @@
1
- import { existsSync } from "node:fs";
1
+ import { existsSync, readFileSync } from "node:fs";
2
2
  import { mkdir, readdir, readFile } from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { DatabaseSync } from "node:sqlite";
6
+ import { logForgeDebug } from "./debug.js";
6
7
  import { ensureQuestionnaireSeeds } from "./repositories/questionnaires.js";
8
+ import { getMonorepoRuntimePreferencePath } from "./runtime-data-root.js";
7
9
  function nowIso() {
8
10
  return new Date().toISOString();
9
11
  }
@@ -15,15 +17,62 @@ function dateOffsetIso(days) {
15
17
  const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
16
18
  const migrationsDir = path.join(projectRoot, "server", "migrations");
17
19
  const monorepoForgeDataRoot = path.resolve(projectRoot, "..", "..", "data", "forge");
20
+ function resolveCanonicalDataDir(root = dataRoot) {
21
+ return path.resolve(root);
22
+ }
23
+ function resolveLegacyDataDir(root = dataRoot) {
24
+ return path.join(path.resolve(root), "data");
25
+ }
26
+ function resolveCanonicalDatabasePath(root = dataRoot) {
27
+ return path.join(resolveCanonicalDataDir(root), "forge.sqlite");
28
+ }
29
+ function resolveLegacyDatabasePath(root = dataRoot) {
30
+ return path.join(resolveLegacyDataDir(root), "forge.sqlite");
31
+ }
32
+ function hasCanonicalRuntimeLayout(root = dataRoot) {
33
+ const canonicalRoot = resolveCanonicalDataDir(root);
34
+ return (existsSync(resolveCanonicalDatabasePath(root)) ||
35
+ existsSync(path.join(canonicalRoot, "wiki")) ||
36
+ existsSync(path.join(canonicalRoot, "wiki-ingest")) ||
37
+ existsSync(path.join(canonicalRoot, ".forge-secrets.key")));
38
+ }
39
+ function hasLegacyRuntimeLayout(root = dataRoot) {
40
+ const legacyRoot = resolveLegacyDataDir(root);
41
+ return (existsSync(resolveLegacyDatabasePath(root)) ||
42
+ existsSync(path.join(legacyRoot, "wiki")) ||
43
+ existsSync(path.join(legacyRoot, "wiki-ingest")) ||
44
+ existsSync(path.join(legacyRoot, ".forge-secrets.key")));
45
+ }
46
+ export function resolveDatabasePathForDataRoot(root = dataRoot) {
47
+ if (existsSync(resolveCanonicalDatabasePath(root))) {
48
+ return resolveCanonicalDatabasePath(root);
49
+ }
50
+ if (existsSync(resolveLegacyDatabasePath(root))) {
51
+ return resolveLegacyDatabasePath(root);
52
+ }
53
+ return resolveCanonicalDatabasePath(root);
54
+ }
18
55
  export function resolveDefaultDataRoot(currentWorkingDir = process.cwd()) {
19
56
  const configured = process.env.FORGE_DATA_ROOT?.trim();
20
57
  if (configured) {
21
58
  return path.resolve(configured);
22
59
  }
60
+ if (existsSync(getMonorepoRuntimePreferencePath())) {
61
+ try {
62
+ const raw = readFileSync(getMonorepoRuntimePreferencePath(), "utf8");
63
+ const parsed = JSON.parse(raw);
64
+ if (typeof parsed.dataRoot === "string" && parsed.dataRoot.trim().length > 0) {
65
+ return path.resolve(parsed.dataRoot);
66
+ }
67
+ }
68
+ catch {
69
+ // Ignore invalid local runtime preference files and continue to defaults.
70
+ }
71
+ }
23
72
  // Inside the private monorepo, prefer the tracked shared Forge data root so
24
73
  // the local app, Hermes, OpenClaw, and repo-managed data all point at the
25
74
  // same state by default.
26
- if (existsSync(path.join(monorepoForgeDataRoot, "data"))) {
75
+ if (existsSync(monorepoForgeDataRoot)) {
27
76
  return monorepoForgeDataRoot;
28
77
  }
29
78
  return path.resolve(currentWorkingDir);
@@ -34,13 +83,29 @@ let db = null;
34
83
  let transactionDepth = 0;
35
84
  let savepointCounter = 0;
36
85
  function getDataDir() {
37
- return path.join(dataRoot, "data");
86
+ const databasePath = resolveDatabasePathForDataRoot();
87
+ if (databasePath === resolveCanonicalDatabasePath()) {
88
+ return resolveCanonicalDataDir();
89
+ }
90
+ if (databasePath === resolveLegacyDatabasePath()) {
91
+ return resolveLegacyDataDir();
92
+ }
93
+ if (hasCanonicalRuntimeLayout()) {
94
+ return resolveCanonicalDataDir();
95
+ }
96
+ if (hasLegacyRuntimeLayout()) {
97
+ return resolveLegacyDataDir();
98
+ }
99
+ return resolveCanonicalDataDir();
38
100
  }
39
101
  export function resolveDataDir() {
40
102
  return getDataDir();
41
103
  }
104
+ export function getEffectiveDataRoot() {
105
+ return dataRoot;
106
+ }
42
107
  function getDatabasePath() {
43
- return path.join(getDataDir(), "forge.sqlite");
108
+ return resolveDatabasePathForDataRoot();
44
109
  }
45
110
  export function getDatabase() {
46
111
  if (!db) {
@@ -289,6 +354,7 @@ export async function initializeDatabase() {
289
354
  await mkdir(getDataDir(), { recursive: true });
290
355
  const database = getDatabase();
291
356
  const migrationFiles = await listMigrationFiles();
357
+ const pendingMigrations = [];
292
358
  database.exec(`
293
359
  CREATE TABLE IF NOT EXISTS migrations (
294
360
  id TEXT PRIMARY KEY,
@@ -303,6 +369,7 @@ export async function initializeDatabase() {
303
369
  if (applied.has(file)) {
304
370
  continue;
305
371
  }
372
+ pendingMigrations.push(file);
306
373
  const sql = await readFile(path.join(migrationsDir, file), "utf8");
307
374
  database.exec("BEGIN");
308
375
  try {
@@ -317,6 +384,7 @@ export async function initializeDatabase() {
317
384
  throw error;
318
385
  }
319
386
  }
387
+ logForgeDebug(`[forge-db] initialized database path=${getDatabasePath()} applied_count=${appliedRows.length} pending_applied=${pendingMigrations.length} pending_list=${pendingMigrations.join(",") || "none"}`);
320
388
  if (seedDemoDataEnabled) {
321
389
  seedData();
322
390
  }
@@ -0,0 +1,19 @@
1
+ function isTruthyFlag(value) {
2
+ if (!value) {
3
+ return false;
4
+ }
5
+ const normalized = value.trim().toLowerCase();
6
+ return (normalized === "1" ||
7
+ normalized === "true" ||
8
+ normalized === "yes" ||
9
+ normalized === "on");
10
+ }
11
+ export function isForgeDebugLoggingEnabled(env = process.env) {
12
+ return isTruthyFlag(env.FORGE_DEBUG_LOGS);
13
+ }
14
+ export function logForgeDebug(message, env = process.env) {
15
+ if (!isForgeDebugLoggingEnabled(env)) {
16
+ return;
17
+ }
18
+ console.info(message);
19
+ }
@@ -1,5 +1,5 @@
1
1
  import path from "node:path";
2
- import { closeDatabase, configureDatabase, configureDatabaseSeeding, getDatabase, initializeDatabase } from "./db.js";
2
+ import { closeDatabase, configureDatabase, configureDatabaseSeeding, getDatabase, initializeDatabase, resolveDatabasePathForDataRoot } from "./db.js";
3
3
  const PERSONAL_CONTENT_TABLES = [
4
4
  "goals",
5
5
  "projects",
@@ -23,7 +23,7 @@ function getCounts() {
23
23
  }
24
24
  export async function seedDemoDataIntoRuntime(dataRoot = process.env.FORGE_DATA_ROOT ?? process.cwd()) {
25
25
  const resolvedDataRoot = path.resolve(dataRoot);
26
- const databasePath = path.join(resolvedDataRoot, "data", "forge.sqlite");
26
+ const databasePath = resolveDatabasePathForDataRoot(resolvedDataRoot);
27
27
  closeDatabase();
28
28
  configureDatabase({ dataRoot: resolvedDataRoot });
29
29
  configureDatabaseSeeding(false);